mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 15:53:36 +01:00
Compare commits
1848 Commits
v1.3.0
...
feature/ja
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e5c8f28c8 | ||
|
|
e854c37605 | ||
|
|
7229f3bde4 | ||
|
|
b9cf393eb6 | ||
|
|
4baf1687b5 | ||
|
|
8eaf6a9cf0 | ||
|
|
3b294282f3 | ||
|
|
ccd08e0c9d | ||
|
|
62a5db6b8b | ||
|
|
3736161e39 | ||
|
|
92b4a74440 | ||
|
|
f8c18ae270 | ||
|
|
7ca02f06c6 | ||
|
|
61eeaca039 | ||
|
|
03f6777197 | ||
|
|
09a5dd6aa9 | ||
|
|
32cde3b7d8 | ||
|
|
c25bfb98d2 | ||
|
|
62d1b135fb | ||
|
|
dda33932e1 | ||
|
|
00a7197f12 | ||
|
|
33817684cc | ||
|
|
005036a272 | ||
|
|
3ba68d8a34 | ||
|
|
4bedacfdd2 | ||
|
|
41d4f1fcc2 | ||
|
|
23cd3bfa93 | ||
|
|
0a23f44052 | ||
|
|
1c10ff54e7 | ||
|
|
b35f47e9cb | ||
|
|
7c98f19d73 | ||
|
|
2ef3fdcc4e | ||
|
|
40f70c257d | ||
|
|
275d1bdbf9 | ||
|
|
9cf3313f31 | ||
|
|
3e7e5688ef | ||
|
|
90073f48c1 | ||
|
|
71f9831a5c | ||
|
|
1781aadab0 | ||
|
|
d9aa52befb | ||
|
|
3abe415805 | ||
|
|
560f7b6e24 | ||
|
|
5c2fe57252 | ||
|
|
2bd6895bf3 | ||
|
|
79deda799f | ||
|
|
b86fa133c5 | ||
|
|
30622f9c4a | ||
|
|
23159caf2b | ||
|
|
2cd5ced015 | ||
|
|
e9e7f095be | ||
|
|
43af96bb0f | ||
|
|
e8088c2bda | ||
|
|
af303df965 | ||
|
|
48ff396e7e | ||
|
|
a85a0456bc | ||
|
|
b5e7a54d35 | ||
|
|
df031a1bd6 | ||
|
|
f598857a83 | ||
|
|
420f50b9bf | ||
|
|
40699fa1ac | ||
|
|
64e44ad614 | ||
|
|
c6f2bf66e6 | ||
|
|
d27b47c0d5 | ||
|
|
fe2cbdd007 | ||
|
|
3afea40bbb | ||
|
|
536914c3b7 | ||
|
|
302fe1ce05 | ||
|
|
121972ffd9 | ||
|
|
f58ee9896a | ||
|
|
dd4d1495c1 | ||
|
|
16a6a2d2d8 | ||
|
|
b91d086340 | ||
|
|
0f25e53eda | ||
|
|
bb20129f0e | ||
|
|
9be1da7e12 | ||
|
|
6636d7d143 | ||
|
|
8619aadf16 | ||
|
|
3555733bbf | ||
|
|
2d9ad67b14 | ||
|
|
5fc2fcd7d8 | ||
|
|
2a0df96c5b | ||
|
|
4bfb7d341e | ||
|
|
eed32bd4f6 | ||
|
|
8b35fe2683 | ||
|
|
2db2235803 | ||
|
|
05ed69193c | ||
|
|
7b561d559e | ||
|
|
1e72c49eb2 | ||
|
|
63a2874cec | ||
|
|
fd47ede9d6 | ||
|
|
c0a0636fe9 | ||
|
|
412b72540a | ||
|
|
a1012ded26 | ||
|
|
782a9dea7a | ||
|
|
df4cc59efa | ||
|
|
d20c679528 | ||
|
|
872a524c44 | ||
|
|
5a0e597124 | ||
|
|
2d984dda94 | ||
|
|
dc1acc99da | ||
|
|
363399d95f | ||
|
|
d713e5d7d7 | ||
|
|
c6363fde7a | ||
|
|
eddffaae3d | ||
|
|
b46d13fc18 | ||
|
|
482f8daaf3 | ||
|
|
334829604f | ||
|
|
ebff547b6f | ||
|
|
4862811600 | ||
|
|
0a2bfcaed2 | ||
|
|
a31dddf8ef | ||
|
|
19c223161d | ||
|
|
ae128c38ec | ||
|
|
a7dddfa905 | ||
|
|
c465bc9fc7 | ||
|
|
7bcde5d439 | ||
|
|
76d79186c7 | ||
|
|
d7606d0263 | ||
|
|
72c121797f | ||
|
|
f51edf52e7 | ||
|
|
eb023c0c99 | ||
|
|
0e3fa6645d | ||
|
|
93f25abd99 | ||
|
|
f1631e9ff3 | ||
|
|
8c4187967a | ||
|
|
ddb60cab61 | ||
|
|
f7a72489d4 | ||
|
|
c58ec0ff8c | ||
|
|
9e6cf2e6f3 | ||
|
|
332bbe72aa | ||
|
|
0b32d3b991 | ||
|
|
9e92e2f8da | ||
|
|
fb138364d4 | ||
|
|
082ac5d229 | ||
|
|
e18c32c5dc | ||
|
|
5ebc2dc244 | ||
|
|
e4b7f7aa8f | ||
|
|
a754a8e6b4 | ||
|
|
43621016cf | ||
|
|
741fba51f5 | ||
|
|
4a3f8c4f2a | ||
|
|
14839cadf5 | ||
|
|
d560ca927e | ||
|
|
eacb4c9d62 | ||
|
|
804f8e38da | ||
|
|
7e1b6d0cc7 | ||
|
|
3440edbfb6 | ||
|
|
2a1186c4fa | ||
|
|
af63b40307 | ||
|
|
38499898aa | ||
|
|
dea9fa1145 | ||
|
|
49d14d1272 | ||
|
|
f8bf9d4eb7 | ||
|
|
0536fa6c2a | ||
|
|
16977e4869 | ||
|
|
5cb1d93029 | ||
|
|
376fe38a02 | ||
|
|
fda21e3eff | ||
|
|
6197660292 | ||
|
|
f474276807 | ||
|
|
5c44ea19cc | ||
|
|
95331082d5 | ||
|
|
0a344912d3 | ||
|
|
7952df0883 | ||
|
|
02785f2a4a | ||
|
|
8ea104544c | ||
|
|
8428e96702 | ||
|
|
3d11a36671 | ||
|
|
cc2b033e6d | ||
|
|
c0dfacbf6c | ||
|
|
8ebaf055a1 | ||
|
|
2431da4c6e | ||
|
|
088566a2cf | ||
|
|
210dd3f778 | ||
|
|
4776a542a7 | ||
|
|
8ab6b77b56 | ||
|
|
e92e3aa321 | ||
|
|
9077c77908 | ||
|
|
01c7979231 | ||
|
|
7f01829de1 | ||
|
|
ce7c07813b | ||
|
|
c36348611b | ||
|
|
9525ab449f | ||
|
|
5b7a978f01 | ||
|
|
988d1d5147 | ||
|
|
644f4ca6c2 | ||
|
|
8ceaa04320 | ||
|
|
a78f28ade6 | ||
|
|
3a07795e39 | ||
|
|
aab42547ad | ||
|
|
62ca5e890a | ||
|
|
765bfa0e1d | ||
|
|
5b7314e6d3 | ||
|
|
714b3d29b9 | ||
|
|
19fde6d667 | ||
|
|
f42d3bea5a | ||
|
|
60fd4f6311 | ||
|
|
0b3a50f320 | ||
|
|
b8f938b81b | ||
|
|
23a6a726fe | ||
|
|
f4b11d8e44 | ||
|
|
c8bfdddd59 | ||
|
|
f2d1819589 | ||
|
|
e2a97738e1 | ||
|
|
2f6e40f123 | ||
|
|
f6d301fd67 | ||
|
|
c484edf7ae | ||
|
|
667e784d06 | ||
|
|
20ff49f66c | ||
|
|
2332c0fa5e | ||
|
|
fa05482e69 | ||
|
|
2ef4237adf | ||
|
|
79b7d74387 | ||
|
|
b3d034a435 | ||
|
|
f5ec0331eb | ||
|
|
b4661d85f4 | ||
|
|
f15edfb806 | ||
|
|
143c8d151f | ||
|
|
01ff6d986c | ||
|
|
c153463471 | ||
|
|
e90444f012 | ||
|
|
55b9a42b62 | ||
|
|
c51c772ff6 | ||
|
|
2507a56a3a | ||
|
|
77b4372eff | ||
|
|
8a7066cda7 | ||
|
|
51d7618661 | ||
|
|
4b0164cffb | ||
|
|
d18a63635d | ||
|
|
51cf98eb60 | ||
|
|
4370dfcd5a | ||
|
|
664f083071 | ||
|
|
57e729512e | ||
|
|
818b8b295f | ||
|
|
c8dd241567 | ||
|
|
ed49251310 | ||
|
|
98f9628e27 | ||
|
|
bfbec1d0a6 | ||
|
|
6ddc0bfa27 | ||
|
|
eacf3ac906 | ||
|
|
6fc15984b8 | ||
|
|
cd875777e7 | ||
|
|
a38f8b447c | ||
|
|
142eb41312 | ||
|
|
1835355f4d | ||
|
|
3c3534e7da | ||
|
|
27abb72df1 | ||
|
|
159b9006cc | ||
|
|
54ccd04c17 | ||
|
|
cf2f2dc62d | ||
|
|
52b55434eb | ||
|
|
f5e16ea6ee | ||
|
|
16892d022f | ||
|
|
fa377cfc05 | ||
|
|
423216f1a3 | ||
|
|
b6936bf805 | ||
|
|
3b019d173c | ||
|
|
1be196698d | ||
|
|
cd018def91 | ||
|
|
9c0a166b7d | ||
|
|
516390827b | ||
|
|
bb5b6b75b8 | ||
|
|
c33cc3f230 | ||
|
|
4fc8dd59d2 | ||
|
|
04dc5f8491 | ||
|
|
e0af41e439 | ||
|
|
1564f11b89 | ||
|
|
69323bf0a4 | ||
|
|
6726101e36 | ||
|
|
9998cd0ccc | ||
|
|
562269dd2b | ||
|
|
a8b740a538 | ||
|
|
7a74917b67 | ||
|
|
4a95efefac | ||
|
|
9b718490e3 | ||
|
|
4e745c9c89 | ||
|
|
4ac0a0e305 | ||
|
|
3b00b764ac | ||
|
|
8595f55eb3 | ||
|
|
67aa59c4b8 | ||
|
|
165170e5d4 | ||
|
|
816e17a67b | ||
|
|
a98b946354 | ||
|
|
a5c3ecf6de | ||
|
|
c998bff178 | ||
|
|
620e518e92 | ||
|
|
1e96b43720 | ||
|
|
58bf7ff670 | ||
|
|
a0081318b6 | ||
|
|
9175b2624d | ||
|
|
9db7012042 | ||
|
|
9a9cf826ab | ||
|
|
60c2e31cea | ||
|
|
cb6287eacc | ||
|
|
6182ac3307 | ||
|
|
7ee7d2fa1c | ||
|
|
322f0518f9 | ||
|
|
4358952e17 | ||
|
|
82a5b4ab12 | ||
|
|
e45a5a99c3 | ||
|
|
e5eb056324 | ||
|
|
3a0a170904 | ||
|
|
b05bb8a1ee | ||
|
|
a4768386cc | ||
|
|
1bfd2d7ac1 | ||
|
|
1548f9a4b2 | ||
|
|
61390b200d | ||
|
|
df737539a5 | ||
|
|
5bbb386f8c | ||
|
|
bbd59be1d6 | ||
|
|
1b1debdb30 | ||
|
|
37eefc7f8b | ||
|
|
325ed8e47c | ||
|
|
33640ccfbb | ||
|
|
519d90e3d0 | ||
|
|
417fda8c7c | ||
|
|
c31a56228b | ||
|
|
c472608876 | ||
|
|
7f92109bde | ||
|
|
31fb9b0a20 | ||
|
|
a967735e11 | ||
|
|
d8f79fa51d | ||
|
|
3bf69651fd | ||
|
|
ed22b6532f | ||
|
|
c4ee53e147 | ||
|
|
cc256d5ef0 | ||
|
|
f51a7371b7 | ||
|
|
235df3e482 | ||
|
|
f36f4068f3 | ||
|
|
9b491fb286 | ||
|
|
dc41cb7674 | ||
|
|
070f4edce1 | ||
|
|
ab5de24518 | ||
|
|
795de6f9ea | ||
|
|
7eda83a434 | ||
|
|
190fa55ace | ||
|
|
ff7ebf405c | ||
|
|
74a2326e0e | ||
|
|
c4b67a1db2 | ||
|
|
ae50b01318 | ||
|
|
e203bc63e9 | ||
|
|
f700b22358 | ||
|
|
dc1195f8b1 | ||
|
|
8f582c55d1 | ||
|
|
e82bbbefe8 | ||
|
|
aa033cde4b | ||
|
|
af02238f01 | ||
|
|
2421380d1d | ||
|
|
c8a73afe84 | ||
|
|
0f87dee1a0 | ||
|
|
5ff9814894 | ||
|
|
5d87dc2942 | ||
|
|
1049a18a15 | ||
|
|
e07401dc55 | ||
|
|
bcae8d2015 | ||
|
|
631c10f8b6 | ||
|
|
a015cf4210 | ||
|
|
07f838ccf3 | ||
|
|
d06d561a55 | ||
|
|
6567c971e1 | ||
|
|
d6eac2b3c8 | ||
|
|
ec3aec6445 | ||
|
|
a9449fe5ff | ||
|
|
d7b6988e2e | ||
|
|
c39e223f0f | ||
|
|
06f59893af | ||
|
|
6d7f7d8e42 | ||
|
|
e7055c8a38 | ||
|
|
ab2e5f31c8 | ||
|
|
828ff5a1ec | ||
|
|
60b1775e37 | ||
|
|
c0aca39d31 | ||
|
|
bf5aafe455 | ||
|
|
fb2b3159e8 | ||
|
|
9ebbbe6a5b | ||
|
|
593fddb1f9 | ||
|
|
3ef80644f8 | ||
|
|
d401a7e60a | ||
|
|
1e269f2a2c | ||
|
|
333dc96d6f | ||
|
|
ade69168d0 | ||
|
|
89c63ac5c9 | ||
|
|
9fd8f1c898 | ||
|
|
b44862f713 | ||
|
|
4da950f37c | ||
|
|
10a8bf5356 | ||
|
|
a06c6dda40 | ||
|
|
c6c194dddb | ||
|
|
a13d29b0cc | ||
|
|
1caca99e82 | ||
|
|
0336fcb7a3 | ||
|
|
95c0d9b9a0 | ||
|
|
240d06d7e4 | ||
|
|
2753bb97c8 | ||
|
|
9c744211d7 | ||
|
|
8a8d4fb994 | ||
|
|
d24dac26ea | ||
|
|
93088c2e9a | ||
|
|
61ad90c939 | ||
|
|
c849af19ed | ||
|
|
4f7ce49dea | ||
|
|
c94717bd1c | ||
|
|
06cf39b59b | ||
|
|
c3c52c2b2a | ||
|
|
b4dcd61f58 | ||
|
|
89b8f314d8 | ||
|
|
e975ba5199 | ||
|
|
12d74510cd | ||
|
|
176363492e | ||
|
|
b8edcaeaf8 | ||
|
|
db2a0abcb6 | ||
|
|
84c6320e49 | ||
|
|
cc2051b308 | ||
|
|
43d71e7665 | ||
|
|
37b9f49467 | ||
|
|
79d64a617d | ||
|
|
784a1393fc | ||
|
|
af9bc9ec3e | ||
|
|
f3580dece7 | ||
|
|
0183457b7a | ||
|
|
60b8bde19a | ||
|
|
5e8b012a5d | ||
|
|
5703a44ab5 | ||
|
|
91b1d5cbde | ||
|
|
2ab92a940b | ||
|
|
4ec8e3bbbb | ||
|
|
ed56eb2ec1 | ||
|
|
d4c1a9ea08 | ||
|
|
48947ca722 | ||
|
|
5d028ee9fe | ||
|
|
35b762bd75 | ||
|
|
cbb10a1b1c | ||
|
|
239c5f2e46 | ||
|
|
d7d5e0c757 | ||
|
|
fccac8cb85 | ||
|
|
6d2a6bbd3d | ||
|
|
4fc2abd183 | ||
|
|
b762d8e664 | ||
|
|
ccce1eea4b | ||
|
|
11ef55920e | ||
|
|
7c0a7a0dd0 | ||
|
|
e6ec9d9aa3 | ||
|
|
1fe24a2e0c | ||
|
|
f2aa3f12be | ||
|
|
cb3cf79beb | ||
|
|
a27f390d37 | ||
|
|
d8107c1232 | ||
|
|
9272bded7e | ||
|
|
6800029163 | ||
|
|
64c824fedf | ||
|
|
8338668ab4 | ||
|
|
eb244e0234 | ||
|
|
3ffb2d1312 | ||
|
|
d76832f761 | ||
|
|
d5503ff615 | ||
|
|
87f327b095 | ||
|
|
756d39df9a | ||
|
|
fa4d8832d7 | ||
|
|
9d0a5da783 | ||
|
|
725f1e9759 | ||
|
|
55689fe911 | ||
|
|
de4c116271 | ||
|
|
10ebe49287 | ||
|
|
305db5f8b1 | ||
|
|
6e2b82c446 | ||
|
|
db135f8e11 | ||
|
|
c3b5d2f620 | ||
|
|
02052799ed | ||
|
|
9f31c33938 | ||
|
|
dd1cadf621 | ||
|
|
5bc1c3f616 | ||
|
|
c555f60f47 | ||
|
|
a4ea892f20 | ||
|
|
2cb017cf83 | ||
|
|
ac830d5784 | ||
|
|
1db9add9ff | ||
|
|
9936b1339c | ||
|
|
7a373799cf | ||
|
|
466562df41 | ||
|
|
b9e9c837c8 | ||
|
|
9b289e619a | ||
|
|
006b180a0c | ||
|
|
abcb5c3a32 | ||
|
|
0c0151e550 | ||
|
|
dee1ccfd3e | ||
|
|
af2259d69e | ||
|
|
131caf0e3e | ||
|
|
3d5b86d96f | ||
|
|
9a30c3d0cb | ||
|
|
7545329db2 | ||
|
|
066c331f96 | ||
|
|
7ccfee73bc | ||
|
|
3f7a9b92ec | ||
|
|
5d15c60c68 | ||
|
|
dacf493a94 | ||
|
|
65ad53f59e | ||
|
|
b0cf555b6e | ||
|
|
d0bfe114f6 | ||
|
|
4f4e734eee | ||
|
|
37ea0bf05b | ||
|
|
31463597ef | ||
|
|
8b2c6d6918 | ||
|
|
9c52ffc48f | ||
|
|
74dd1e6359 | ||
|
|
74fbaeefbf | ||
|
|
fec0878091 | ||
|
|
f257388108 | ||
|
|
99828b5cb3 | ||
|
|
d56f452f31 | ||
|
|
9f52bf5dc9 | ||
|
|
aed980f79d | ||
|
|
f219cb69d4 | ||
|
|
936830084e | ||
|
|
2e35c5bcab | ||
|
|
a13c6fcb25 | ||
|
|
c748d59146 | ||
|
|
d1ac0de740 | ||
|
|
0075a7e1ce | ||
|
|
091108a369 | ||
|
|
0be494a211 | ||
|
|
8021aaed4b | ||
|
|
584fd2a47b | ||
|
|
237dbe7061 | ||
|
|
ed214d05fa | ||
|
|
76218da8d1 | ||
|
|
869c9c0114 | ||
|
|
c3c1869829 | ||
|
|
e2617b7434 | ||
|
|
5607e1f179 | ||
|
|
23ad3d04b0 | ||
|
|
d498c7c7b0 | ||
|
|
66dbcb98d2 | ||
|
|
422418f396 | ||
|
|
31ad7adadd | ||
|
|
b3216effa4 | ||
|
|
060cfd625e | ||
|
|
38c0882a3a | ||
|
|
a47d46914a | ||
|
|
789a57b430 | ||
|
|
6b359a7138 | ||
|
|
e9e7042923 | ||
|
|
1fff0db18c | ||
|
|
516129533e | ||
|
|
ca4da60dc1 | ||
|
|
c3ff5bac54 | ||
|
|
a07ab11f9f | ||
|
|
bbf0b295ce | ||
|
|
ed09242cb7 | ||
|
|
52b2b4794e | ||
|
|
4293cce282 | ||
|
|
839d869137 | ||
|
|
a8add14255 | ||
|
|
6ca6d4d71c | ||
|
|
ee1934f74b | ||
|
|
69f39d4dfe | ||
|
|
d355cab2f9 | ||
|
|
217b08b571 | ||
|
|
72aec26ede | ||
|
|
a076ce6e8e | ||
|
|
ec448438e5 | ||
|
|
9777406460 | ||
|
|
7956606876 | ||
|
|
04e0b95a8a | ||
|
|
1b14c10085 | ||
|
|
d5df4920c7 | ||
|
|
576e26144d | ||
|
|
e411c03e7f | ||
|
|
bf5f1df8a7 | ||
|
|
986ad0584d | ||
|
|
6d2ac67011 | ||
|
|
3bdc6988b3 | ||
|
|
e86225c1e1 | ||
|
|
3e4d012a69 | ||
|
|
dccbd659ed | ||
|
|
1b84095c0e | ||
|
|
c96ef88222 | ||
|
|
0540474e0c | ||
|
|
2dbfba9ac5 | ||
|
|
8eff628303 | ||
|
|
8206aa9bfd | ||
|
|
dd4a1f2d56 | ||
|
|
b0f9935fcb | ||
|
|
519167bf0f | ||
|
|
122c78648a | ||
|
|
d457fd1452 | ||
|
|
454a875593 | ||
|
|
e8e06d12c7 | ||
|
|
006224b52c | ||
|
|
6007be1b5f | ||
|
|
6b5cfe1560 | ||
|
|
f584be7f44 | ||
|
|
b6a7d0ee9b | ||
|
|
1402b20a6b | ||
|
|
898412eaea | ||
|
|
7753b6f3c1 | ||
|
|
ea93f315d5 | ||
|
|
7f9cf5bb14 | ||
|
|
c4fe921670 | ||
|
|
693c08cfd3 | ||
|
|
9776f38b97 | ||
|
|
ff91d7cda7 | ||
|
|
e218b8ad70 | ||
|
|
555b1dc1cc | ||
|
|
523eed9319 | ||
|
|
9c7f6daf75 | ||
|
|
f2037b3fab | ||
|
|
c545285f7f | ||
|
|
290cd0507e | ||
|
|
ee72f172d2 | ||
|
|
e721dac389 | ||
|
|
4c15993a44 | ||
|
|
8fc42078c7 | ||
|
|
06d6fe4bd6 | ||
|
|
96cda322a3 | ||
|
|
0c991af58d | ||
|
|
3677b5f429 | ||
|
|
fd0abd9066 | ||
|
|
abb10600f7 | ||
|
|
c9a6bb4b16 | ||
|
|
9ff0042527 | ||
|
|
0504f9c4cc | ||
|
|
7b7861206b | ||
|
|
6f9207fe25 | ||
|
|
de6cd3621b | ||
|
|
04b506662f | ||
|
|
c1250fc53e | ||
|
|
c2f521f528 | ||
|
|
5fde08b001 | ||
|
|
69d621b981 | ||
|
|
4134fb3fef | ||
|
|
81b2b966ba | ||
|
|
ae65ebe687 | ||
|
|
03f84fa77e | ||
|
|
ff6b3dbd4f | ||
|
|
bf7b8ccce8 | ||
|
|
57b1895b5e | ||
|
|
8edf65186f | ||
|
|
13d781d2b1 | ||
|
|
7c1c99f5f9 | ||
|
|
0a02f43b8c | ||
|
|
d4e50d9560 | ||
|
|
5681e0bfdf | ||
|
|
55bfe4cad8 | ||
|
|
d726792be6 | ||
|
|
5c21451760 | ||
|
|
b3736ac13a | ||
|
|
a4899de956 | ||
|
|
e3ca70ba0d | ||
|
|
bdace1b1b7 | ||
|
|
567022a9b7 | ||
|
|
83262afd13 | ||
|
|
3ff838a2cc | ||
|
|
40b5c45ef6 | ||
|
|
d2a8645dd4 | ||
|
|
4543835a0d | ||
|
|
c0f41c461b | ||
|
|
116ef264e1 | ||
|
|
1371dacdaa | ||
|
|
d252d0f29f | ||
|
|
3786f6ebc7 | ||
|
|
6813427867 | ||
|
|
9da95e592c | ||
|
|
f94cf106a6 | ||
|
|
a67e421a5d | ||
|
|
865db1b6c3 | ||
|
|
31d7379a39 | ||
|
|
f473e63a61 | ||
|
|
c9ee55863f | ||
|
|
238a96184a | ||
|
|
44ddad8101 | ||
|
|
afa47f7dfc | ||
|
|
f289bcd285 | ||
|
|
c7adb1bb65 | ||
|
|
4bbc5e27b5 | ||
|
|
c877ade004 | ||
|
|
ebd8996ad5 | ||
|
|
f31313d021 | ||
|
|
6936dac9b4 | ||
|
|
4b2f6832fe | ||
|
|
c622ff2b19 | ||
|
|
35d0f21c47 | ||
|
|
3066d286c5 | ||
|
|
18564e8e86 | ||
|
|
832cbabc7d | ||
|
|
8b764d5e17 | ||
|
|
e2a1a59543 | ||
|
|
cedb8d3db1 | ||
|
|
539bd754df | ||
|
|
109f5c22e9 | ||
|
|
a23d127c62 | ||
|
|
6825304100 | ||
|
|
947499726a | ||
|
|
97b2e1a4da | ||
|
|
2b04c6a7dd | ||
|
|
3bb6553111 | ||
|
|
371dba948d | ||
|
|
675349c06f | ||
|
|
7a88981aa4 | ||
|
|
626f6c3de2 | ||
|
|
5540397456 | ||
|
|
69c6dd40a1 | ||
|
|
5ed6e838fc | ||
|
|
1d32a6012a | ||
|
|
b157049a7e | ||
|
|
8ea6b08a0a | ||
|
|
8856ff04ec | ||
|
|
8bfbd11a51 | ||
|
|
abd843d281 | ||
|
|
c54f9b1144 | ||
|
|
318f3e14dd | ||
|
|
46f227e92e | ||
|
|
a7b6f37503 | ||
|
|
a61bba2f72 | ||
|
|
dfc6d952bd | ||
|
|
046f4605f9 | ||
|
|
32590ab7ff | ||
|
|
efeb084e57 | ||
|
|
03ec3142c3 | ||
|
|
679df936e7 | ||
|
|
5ed5764ab5 | ||
|
|
d588092727 | ||
|
|
295ba0679d | ||
|
|
bcdf26c88d | ||
|
|
d6e092bfa2 | ||
|
|
388c1b5af1 | ||
|
|
717aea9a03 | ||
|
|
4951ee5a62 | ||
|
|
666150cf7f | ||
|
|
d8290c0c45 | ||
|
|
e363e8109b | ||
|
|
b228d08843 | ||
|
|
3e08437808 | ||
|
|
e0d5651b75 | ||
|
|
59e29b7afe | ||
|
|
d180208e34 | ||
|
|
0ce1ef596c | ||
|
|
5f7486f851 | ||
|
|
03559fd106 | ||
|
|
d08357a1c2 | ||
|
|
c1cb87ebde | ||
|
|
82fd1cf4d7 | ||
|
|
a87391e609 | ||
|
|
3071cfd7be | ||
|
|
583c2d34d3 | ||
|
|
c9640fbf04 | ||
|
|
192d1de944 | ||
|
|
aa0314c840 | ||
|
|
0171b859c6 | ||
|
|
d267e14b73 | ||
|
|
79e63f4067 | ||
|
|
72d7af5291 | ||
|
|
0e313d1910 | ||
|
|
6841f9a009 | ||
|
|
caeec68999 | ||
|
|
541915a5a7 | ||
|
|
cb75ab8cca | ||
|
|
0f3845b16d | ||
|
|
dd7128095e | ||
|
|
1367be510c | ||
|
|
2ea0eb3c64 | ||
|
|
a5990ea6f3 | ||
|
|
67921f5f3d | ||
|
|
d31e0453bd | ||
|
|
ae21424a30 | ||
|
|
3577949425 | ||
|
|
0d72471502 | ||
|
|
17590a6d38 | ||
|
|
d9dcc8cc2d | ||
|
|
df1ee5e8c6 | ||
|
|
3c68ebece7 | ||
|
|
c9e8e6cf0e | ||
|
|
36945fb84d | ||
|
|
960a2e27ab | ||
|
|
71724461a9 | ||
|
|
ae5a95bfb3 | ||
|
|
d6c9fea354 | ||
|
|
d6f1351f6b | ||
|
|
373488adb4 | ||
|
|
59401cc9f8 | ||
|
|
eca0e7a852 | ||
|
|
563dc24854 | ||
|
|
3a70e25983 | ||
|
|
a9fc6bf02c | ||
|
|
cd4f09dc86 | ||
|
|
4193718571 | ||
|
|
0464626e2b | ||
|
|
a0198e34e7 | ||
|
|
0b329bd40e | ||
|
|
3d33f24f09 | ||
|
|
886c02fad2 | ||
|
|
3a11504153 | ||
|
|
3a082ae00a | ||
|
|
780201845b | ||
|
|
0e0a4bb0b4 | ||
|
|
5333083a78 | ||
|
|
b8c6c86330 | ||
|
|
e246757f47 | ||
|
|
4172300799 | ||
|
|
f39f754b7b | ||
|
|
c59615f452 | ||
|
|
847bed2fa0 | ||
|
|
a9af15f6f8 | ||
|
|
92519ae955 | ||
|
|
2d90aca1f2 | ||
|
|
f29ed38c34 | ||
|
|
df8d4fd77c | ||
|
|
baa2e2c6ff | ||
|
|
9d5769bb69 | ||
|
|
4cdfa804ee | ||
|
|
523cd23b6b | ||
|
|
61866e9e76 | ||
|
|
ff7fbdc98d | ||
|
|
b625d642ea | ||
|
|
8733a85ebb | ||
|
|
5ab5a7b72b | ||
|
|
3cb8b9fa9e | ||
|
|
429039bf1c | ||
|
|
29d28c3408 | ||
|
|
372d484440 | ||
|
|
eac47800a3 | ||
|
|
86a85db12b | ||
|
|
4ab6cd278c | ||
|
|
233a068c8b | ||
|
|
d9f0ffa742 | ||
|
|
8d63ee19ed | ||
|
|
1fb74e1a27 | ||
|
|
c94ab6108c | ||
|
|
bf285e19ab | ||
|
|
b1ceca73e4 | ||
|
|
f3aca63b61 | ||
|
|
fca107d287 | ||
|
|
64b6964fff | ||
|
|
6af0842838 | ||
|
|
4c49adf1ba | ||
|
|
5f4e4fab56 | ||
|
|
146d7e3fbf | ||
|
|
4d22800747 | ||
|
|
541a7f8180 | ||
|
|
f205cf79c9 | ||
|
|
d8bb6488b7 | ||
|
|
4324563c0a | ||
|
|
bad03660b1 | ||
|
|
20b1ff38f9 | ||
|
|
def78a3cfd | ||
|
|
a41158a716 | ||
|
|
63ad13ff7a | ||
|
|
dd92ec675f | ||
|
|
6e1512f7d9 | ||
|
|
287b1df3fd | ||
|
|
38bf9b4ddb | ||
|
|
f9d3a9d8d8 | ||
|
|
309a5d9bcb | ||
|
|
60e661d3a4 | ||
|
|
c33257d266 | ||
|
|
1dbc183567 | ||
|
|
bf258146da | ||
|
|
bb927b447e | ||
|
|
d91b4c3151 | ||
|
|
91dbb39f18 | ||
|
|
35ae8fd660 | ||
|
|
d854917090 | ||
|
|
32ebf6c8ed | ||
|
|
edd4191d47 | ||
|
|
0cce49506a | ||
|
|
1c053469e9 | ||
|
|
610e97ef7f | ||
|
|
5a678d2ccb | ||
|
|
8db61a4d1e | ||
|
|
f47c6b07f4 | ||
|
|
bd3af45db9 | ||
|
|
a271d422f6 | ||
|
|
4dd6dedaa4 | ||
|
|
10ee569096 | ||
|
|
1474855305 | ||
|
|
0202bc11d4 | ||
|
|
e7072ea04c | ||
|
|
8f2c755f21 | ||
|
|
e513a79bd2 | ||
|
|
dd17f7393f | ||
|
|
32f38bf892 | ||
|
|
d5c3eeaf28 | ||
|
|
bfa67fcba7 | ||
|
|
37a556dcc0 | ||
|
|
fe61f298f0 | ||
|
|
9786c9bf82 | ||
|
|
668161081a | ||
|
|
4978f9dcba | ||
|
|
a6ca2e3895 | ||
|
|
6ecf55be91 | ||
|
|
13bd63dac8 | ||
|
|
db5ff1bfca | ||
|
|
42f2385bb2 | ||
|
|
e9556bbbf0 | ||
|
|
316b936326 | ||
|
|
6838b9b950 | ||
|
|
cdfe5d0c9a | ||
|
|
1610f14c47 | ||
|
|
85ab894b94 | ||
|
|
ddbca24f33 | ||
|
|
6b9acac8c4 | ||
|
|
2333bee5fd | ||
|
|
2ad08d2367 | ||
|
|
1337686013 | ||
|
|
41041bfd18 | ||
|
|
e693e53630 | ||
|
|
b99e13a337 | ||
|
|
3bbc485968 | ||
|
|
e0b549e427 | ||
|
|
75207169e3 | ||
|
|
e07f568237 | ||
|
|
e2cd99d40d | ||
|
|
27f2682a98 | ||
|
|
34a2110e9a | ||
|
|
96ba51db4f | ||
|
|
9c6053a60a | ||
|
|
358367ef9e | ||
|
|
a12bc44ecd | ||
|
|
773ac019f8 | ||
|
|
e751b7b814 | ||
|
|
824aa23b9b | ||
|
|
b7b97960a6 | ||
|
|
40f0e907e1 | ||
|
|
5ff0dc885d | ||
|
|
e70a0ee238 | ||
|
|
9338697079 | ||
|
|
4018a4e1de | ||
|
|
e8788dd2a4 | ||
|
|
e70c2f2b05 | ||
|
|
5ed0583039 | ||
|
|
f76d7295f9 | ||
|
|
6e280c4958 | ||
|
|
48b4ef1944 | ||
|
|
9150df964f | ||
|
|
b2237394e1 | ||
|
|
b3a0f7ad26 | ||
|
|
782ba42abc | ||
|
|
74b93ce602 | ||
|
|
e907c40f17 | ||
|
|
13a9dedb1e | ||
|
|
b37698f245 | ||
|
|
d30d000346 | ||
|
|
446239a5bd | ||
|
|
ac25aa795b | ||
|
|
f117a9ded0 | ||
|
|
947d38ccd2 | ||
|
|
23f7996db8 | ||
|
|
9fdff51f26 | ||
|
|
9b43bf004a | ||
|
|
5d73faa1f0 | ||
|
|
9e70279b31 | ||
|
|
9e671d1065 | ||
|
|
7e2c4af0b3 | ||
|
|
11f9092a65 | ||
|
|
6017e5c217 | ||
|
|
b2149ff4b9 | ||
|
|
1a5177c576 | ||
|
|
7020c9931a | ||
|
|
9bc43e2e8e | ||
|
|
26a4e7451e | ||
|
|
3470d33bdc | ||
|
|
51c96894b4 | ||
|
|
7fc2be6a0a | ||
|
|
110c97bc15 | ||
|
|
8d51d8fa1f | ||
|
|
4b02a567e0 | ||
|
|
5a939ec108 | ||
|
|
d9c4480627 | ||
|
|
9388340e23 | ||
|
|
2285d2ef4b | ||
|
|
f84aea0040 | ||
|
|
452969cc92 | ||
|
|
128a600f18 | ||
|
|
7dd9a52e78 | ||
|
|
ff341b7228 | ||
|
|
92a8b4ca85 | ||
|
|
384199b28d | ||
|
|
44edcabe15 | ||
|
|
1a5e9884fc | ||
|
|
cda81315d2 | ||
|
|
d7100e54d1 | ||
|
|
989caead9c | ||
|
|
a9d3b627f1 | ||
|
|
99a1606df1 | ||
|
|
6326513c63 | ||
|
|
f6cfae595a | ||
|
|
0794efcf41 | ||
|
|
b9ea82f2c1 | ||
|
|
8b705b3370 | ||
|
|
c684607a4d | ||
|
|
b00833c2de | ||
|
|
0ca6bc6ab6 | ||
|
|
60faddff9b | ||
|
|
b35da8ad4b | ||
|
|
79887c148a | ||
|
|
1ae3457ee6 | ||
|
|
d2154c9d29 | ||
|
|
40ede24a99 | ||
|
|
5960ba919d | ||
|
|
f6aaaa8815 | ||
|
|
6f1b20c936 | ||
|
|
7734a50427 | ||
|
|
aef118d375 | ||
|
|
22cae71999 | ||
|
|
29d127303c | ||
|
|
5574f1c24f | ||
|
|
9457744571 | ||
|
|
19243c479c | ||
|
|
e868ce8328 | ||
|
|
ffa846c05a | ||
|
|
dde1791476 | ||
|
|
45438a7f06 | ||
|
|
c980e77ea3 | ||
|
|
176d3ddefa | ||
|
|
98d783d448 | ||
|
|
bcd6634d8a | ||
|
|
0b260cef2a | ||
|
|
6a68abbd67 | ||
|
|
9fcf23c802 | ||
|
|
5c2c08e051 | ||
|
|
1f254997e1 | ||
|
|
4f95af0864 | ||
|
|
6ff39be9d2 | ||
|
|
6cf5a47971 | ||
|
|
56da53c700 | ||
|
|
7091e10795 | ||
|
|
34765c5741 | ||
|
|
36c139872a | ||
|
|
1e77cec677 | ||
|
|
e95e3fb2d0 | ||
|
|
39c2234e38 | ||
|
|
f4fff5d9cb | ||
|
|
659785f972 | ||
|
|
85c04f6e3e | ||
|
|
bef117cbe8 | ||
|
|
46dd7cf86e | ||
|
|
9ed5a97267 | ||
|
|
cc2da70db2 | ||
|
|
cedd93e774 | ||
|
|
632e1692eb | ||
|
|
4861592d2a | ||
|
|
22e6d4edf3 | ||
|
|
e9bd7ff72f | ||
|
|
e7228fb489 | ||
|
|
96c03a68f2 | ||
|
|
4f6f248421 | ||
|
|
a8f14c86fd | ||
|
|
36de3d1e25 | ||
|
|
48bc4570e1 | ||
|
|
94b272dbae | ||
|
|
c093edf459 | ||
|
|
0164feffcc | ||
|
|
8cd377b99f | ||
|
|
74282c8ac5 | ||
|
|
d2158e5e44 | ||
|
|
9ea16ad1d1 | ||
|
|
45941adb71 | ||
|
|
c4d662fd2b | ||
|
|
d9ce3cda66 | ||
|
|
6bd7d6b078 | ||
|
|
84c6dd5dfa | ||
|
|
71e7412f15 | ||
|
|
d22c920b35 | ||
|
|
f7a0982ca0 | ||
|
|
bed04150e1 | ||
|
|
ba15de2218 | ||
|
|
e9ec89dc9c | ||
|
|
d09f75658c | ||
|
|
62f92db181 | ||
|
|
27a98f4244 | ||
|
|
f0a3482eda | ||
|
|
5f76843c4a | ||
|
|
c6ea92cff9 | ||
|
|
c253308284 | ||
|
|
9ae9c111e3 | ||
|
|
4894372eee | ||
|
|
7cf040653f | ||
|
|
034bd4dba0 | ||
|
|
af12a2161c | ||
|
|
57fcf6fde3 | ||
|
|
c5757dc5f4 | ||
|
|
6d5d5ceb7b | ||
|
|
2fa8507d69 | ||
|
|
f23003ead3 | ||
|
|
c996f6b436 | ||
|
|
d2ee66a1c4 | ||
|
|
26b0dd5ef5 | ||
|
|
ad4149a259 | ||
|
|
9611c3b478 | ||
|
|
cead88d221 | ||
|
|
c1e1a6bb4f | ||
|
|
6212a5f740 | ||
|
|
b3d9ea3c47 | ||
|
|
cd51989354 | ||
|
|
b705ae5f0c | ||
|
|
13b53537fa | ||
|
|
7d05aa6073 | ||
|
|
85de173086 | ||
|
|
d264d804c8 | ||
|
|
8272da615e | ||
|
|
857b993d51 | ||
|
|
a71edf584e | ||
|
|
461d7fec0e | ||
|
|
5e3da035dd | ||
|
|
ebb52995a5 | ||
|
|
519b82c620 | ||
|
|
84682d07c6 | ||
|
|
960eeb19af | ||
|
|
ab3920f8f1 | ||
|
|
f5f5857897 | ||
|
|
1c400b410e | ||
|
|
cc751aa224 | ||
|
|
c20892ee3e | ||
|
|
32ab53c9e1 | ||
|
|
d0a7d9eb42 | ||
|
|
a1a9602509 | ||
|
|
cf97c89fe0 | ||
|
|
8895bc85ea | ||
|
|
1a9976c6ca | ||
|
|
f47ebf6145 | ||
|
|
0380715311 | ||
|
|
80ad16c7fa | ||
|
|
e56e9035b6 | ||
|
|
73f22d32d2 | ||
|
|
c3bc56eebc | ||
|
|
35cc14815e | ||
|
|
9be91474f6 | ||
|
|
adf949bf08 | ||
|
|
c6bf41b8ba | ||
|
|
bc656c6218 | ||
|
|
f46226d055 | ||
|
|
00d4ee47de | ||
|
|
c5ffc21660 | ||
|
|
d89b1fdc6a | ||
|
|
8324287bd6 | ||
|
|
6be161a546 | ||
|
|
027350e1ba | ||
|
|
a2309e1c2e | ||
|
|
c34dc97bd4 | ||
|
|
7e8749146e | ||
|
|
8680ecd033 | ||
|
|
4e4417c7af | ||
|
|
7909bbbbe9 | ||
|
|
6fd831e688 | ||
|
|
59a4825c70 | ||
|
|
1ba3681457 | ||
|
|
78becffb2e | ||
|
|
e7efd7070b | ||
|
|
ec6471e8c7 | ||
|
|
b01ae2c6d3 | ||
|
|
ef4a260615 | ||
|
|
f6b80630dd | ||
|
|
f43589589d | ||
|
|
06b59cf79b | ||
|
|
a2187205e0 | ||
|
|
52f269a289 | ||
|
|
310ca967a1 | ||
|
|
c4b423cb0f | ||
|
|
8a6c940aaf | ||
|
|
b295e927b7 | ||
|
|
63d24737dd | ||
|
|
60ce02ba28 | ||
|
|
95939ed66c | ||
|
|
7f609a35be | ||
|
|
f7b534f1ee | ||
|
|
cd5f9e2f13 | ||
|
|
e79da72711 | ||
|
|
1ba081959b | ||
|
|
578dc63652 | ||
|
|
fccd683b50 | ||
|
|
f3d3a25856 | ||
|
|
6d70c92795 | ||
|
|
3c525d8e3a | ||
|
|
a6b47c7c43 | ||
|
|
5b52f01f3d | ||
|
|
d13bbd43f3 | ||
|
|
0394d1a24f | ||
|
|
446222e127 | ||
|
|
05d7aa898d | ||
|
|
73f7fc1d51 | ||
|
|
f0262466d4 | ||
|
|
1ecde9bbc1 | ||
|
|
ae5a766092 | ||
|
|
6a807bc002 | ||
|
|
c0384bb0ee | ||
|
|
2906b315b3 | ||
|
|
425fd65bd8 | ||
|
|
7d83362a85 | ||
|
|
0b26894112 | ||
|
|
17f810a720 | ||
|
|
71ef8061f9 | ||
|
|
353b17690f | ||
|
|
6790727260 | ||
|
|
e129f7db85 | ||
|
|
ea942398e3 | ||
|
|
5ad72cae3f | ||
|
|
5f945bc696 | ||
|
|
6f451736ba | ||
|
|
30856f4a4f | ||
|
|
413c71eb0a | ||
|
|
9d1408be20 | ||
|
|
f21f371751 | ||
|
|
2b761279e4 | ||
|
|
d5e8f54214 | ||
|
|
83f83d4eee | ||
|
|
b0f4ab9ba5 | ||
|
|
06dad8f79c | ||
|
|
83ab122ddf | ||
|
|
8a42fe4ae1 | ||
|
|
94c6778b89 | ||
|
|
c0e5973517 | ||
|
|
1e7bbfa7c1 | ||
|
|
dc7245ff6e | ||
|
|
ffaf7b40e9 | ||
|
|
4de3fb1f2a | ||
|
|
99355d993a | ||
|
|
d25f6e813c | ||
|
|
043f8e0523 | ||
|
|
5fcf2a2623 | ||
|
|
ee77fccffd | ||
|
|
f1422adf75 | ||
|
|
189da08885 | ||
|
|
c2b1742582 | ||
|
|
9e63ac6d5b | ||
|
|
4d7ab8b187 | ||
|
|
4de9818bee | ||
|
|
7a2e1fd221 | ||
|
|
d0ca800a23 | ||
|
|
35ffd56ea9 | ||
|
|
84b992d3a1 | ||
|
|
9e46364759 | ||
|
|
0f37c2b59c | ||
|
|
33852ea7e3 | ||
|
|
4fbed1cdac | ||
|
|
42c61ab457 | ||
|
|
8c6b9f9c68 | ||
|
|
abebecac4a | ||
|
|
87efe429da | ||
|
|
35128b0bd4 | ||
|
|
186cb2270f | ||
|
|
deda02f879 | ||
|
|
bcc2478ef7 | ||
|
|
8d54654482 | ||
|
|
08318107c1 | ||
|
|
a5e77c85a6 | ||
|
|
1e8d2aff75 | ||
|
|
bc0a0f9902 | ||
|
|
da82f975e4 | ||
|
|
48af120db8 | ||
|
|
8722eae766 | ||
|
|
53776936ca | ||
|
|
dca465b801 | ||
|
|
43cd115dc7 | ||
|
|
e7ba08e52c | ||
|
|
9df12e6ff2 | ||
|
|
b5c7fb747c | ||
|
|
a40a4afe80 | ||
|
|
739f595f13 | ||
|
|
e07e892969 | ||
|
|
d4a6c58cc8 | ||
|
|
d644431a4e | ||
|
|
33bbb50b43 | ||
|
|
f89d7df305 | ||
|
|
3b02cd0e39 | ||
|
|
52cd50e0a8 | ||
|
|
996a970081 | ||
|
|
6c0b65acd4 | ||
|
|
f4df263dfe | ||
|
|
8c659acc82 | ||
|
|
7aba2429af | ||
|
|
ab48d2c2ff | ||
|
|
0b699d45bf | ||
|
|
54beafa262 | ||
|
|
531d4923eb | ||
|
|
b160a4d1dd | ||
|
|
ca54daf456 | ||
|
|
a22fc550b3 | ||
|
|
0650d93953 | ||
|
|
5633258fa7 | ||
|
|
12278cda58 | ||
|
|
84d1f08fda | ||
|
|
c184292a57 | ||
|
|
4cdfcb9f9d | ||
|
|
343a78917c | ||
|
|
ff7d0fdb9d | ||
|
|
db26b46be0 | ||
|
|
d77a70c360 | ||
|
|
42f4ae65d1 | ||
|
|
88daac31d2 | ||
|
|
ac04c173a8 | ||
|
|
8401494fbc | ||
|
|
97af118cb9 | ||
|
|
091e6026bc | ||
|
|
c798ede7bf | ||
|
|
225851f067 | ||
|
|
9dd65ecf70 | ||
|
|
1a9cc4b6be | ||
|
|
a612f206bf | ||
|
|
e51031c62a | ||
|
|
e30c29ef50 | ||
|
|
91ddcadbcd | ||
|
|
8c145860e5 | ||
|
|
a19dd7687e | ||
|
|
550d6ca083 | ||
|
|
b425411357 | ||
|
|
a1f0cf749d | ||
|
|
22e0d1c74e | ||
|
|
cdc07047aa | ||
|
|
c832c2da28 | ||
|
|
8daa713639 | ||
|
|
e0a2966706 | ||
|
|
354bfa14f9 | ||
|
|
46b91702ba | ||
|
|
de9516e368 | ||
|
|
3924e07e5c | ||
|
|
76bcbb5a7e | ||
|
|
8022381d1c | ||
|
|
feb1233081 | ||
|
|
36eefd0836 | ||
|
|
0e31e59759 | ||
|
|
4a4c1e75da | ||
|
|
b0bfd2292a | ||
|
|
7214b24357 | ||
|
|
24637f496f | ||
|
|
d8ecde5265 | ||
|
|
28840c6209 | ||
|
|
1696213406 | ||
|
|
6f315ac765 | ||
|
|
a485307d92 | ||
|
|
3d3b861ba0 | ||
|
|
4b33ed25d5 | ||
|
|
e264880c7b | ||
|
|
ef8212701f | ||
|
|
492157a502 | ||
|
|
2605bc182e | ||
|
|
fe8dfdd804 | ||
|
|
bd917bc990 | ||
|
|
c5c32f683f | ||
|
|
5506e58c98 | ||
|
|
5af2d49b18 | ||
|
|
0fd35a4925 | ||
|
|
7ed20b1244 | ||
|
|
efa6a78255 | ||
|
|
8b58df3b34 | ||
|
|
0d2a090e1f | ||
|
|
7860d635a9 | ||
|
|
ba91c9fa9b | ||
|
|
b3630e0d5e | ||
|
|
f752285912 | ||
|
|
5a150d9b0e | ||
|
|
f0aa185832 | ||
|
|
9592f058d4 | ||
|
|
f630794e22 | ||
|
|
93636e89c5 | ||
|
|
585002c25c | ||
|
|
412ccc1be1 | ||
|
|
8b1306a36c | ||
|
|
81026e8dca | ||
|
|
dd440c8f9f | ||
|
|
76f3e4b27e | ||
|
|
5f5d3fdb66 | ||
|
|
853c92b87d | ||
|
|
00080f2abc | ||
|
|
55414208a3 | ||
|
|
5091499563 | ||
|
|
944b54d920 | ||
|
|
d023b2b2ff | ||
|
|
b45f9f514b | ||
|
|
239a9383e0 | ||
|
|
2190c0229c | ||
|
|
01ef14dc92 | ||
|
|
7b0784843c | ||
|
|
6fc805369e | ||
|
|
9e29939cd3 | ||
|
|
d750abca22 | ||
|
|
31df2fa131 | ||
|
|
6355a29a7a | ||
|
|
86a2b38340 | ||
|
|
9cb2b58557 | ||
|
|
2b0e2e8d0d | ||
|
|
cf46767196 | ||
|
|
ffc1034b5a | ||
|
|
46bb19de9b | ||
|
|
70bc7a6d01 | ||
|
|
3164505273 | ||
|
|
3d84fcd037 | ||
|
|
578fa32243 | ||
|
|
fc00b7d1cc | ||
|
|
d7351bd3e5 | ||
|
|
e7224c8f05 | ||
|
|
b97622f45b | ||
|
|
0e15f3b703 | ||
|
|
6604c0da89 | ||
|
|
e0b8be20b3 | ||
|
|
46965d8c96 | ||
|
|
66e92f00ee | ||
|
|
4a137b4e8e | ||
|
|
9d5ff28098 | ||
|
|
313b114da5 | ||
|
|
1b6bfc6338 | ||
|
|
49fd89f34a | ||
|
|
a2e862886e | ||
|
|
62f6c7c5a9 | ||
|
|
2294ed1ce1 | ||
|
|
c8a1c6a318 | ||
|
|
600ed66d5b | ||
|
|
512b17555c | ||
|
|
dc7849c9e8 | ||
|
|
6a99a51b91 | ||
|
|
8c7fa022a0 | ||
|
|
cca694a580 | ||
|
|
3a7f95b9b1 | ||
|
|
3a84dc3962 | ||
|
|
5961a96a4c | ||
|
|
a22382505f | ||
|
|
5faef75415 | ||
|
|
fed60907dc | ||
|
|
ce7e360b70 | ||
|
|
0b3def38b8 | ||
|
|
25a15dea8c | ||
|
|
e204971a6c | ||
|
|
d5b3a118bc | ||
|
|
3396cb2887 | ||
|
|
3c5beea218 | ||
|
|
e544384dd5 | ||
|
|
0e90f460f4 | ||
|
|
921efc4d2b | ||
|
|
1b3b4a5906 | ||
|
|
5c8b374352 | ||
|
|
e05cef6886 | ||
|
|
cb39ecacf9 | ||
|
|
e6816f94eb | ||
|
|
8b5dbeab44 | ||
|
|
29c21c3611 | ||
|
|
e05bed8d65 | ||
|
|
1b2210aba0 | ||
|
|
7fb1b1d57b | ||
|
|
a3adf71a1d | ||
|
|
51d81fab5d | ||
|
|
2ed5dc153a | ||
|
|
5f8f156bee | ||
|
|
eb03c90d7a | ||
|
|
fc05471086 | ||
|
|
b9db2dd89f | ||
|
|
de7fe21a4f | ||
|
|
56f9a7c4f9 | ||
|
|
df569a5ae2 | ||
|
|
acb9d04c51 | ||
|
|
09c4708a22 | ||
|
|
b346dfe0a3 | ||
|
|
5f259cb88c | ||
|
|
fb2aff3310 | ||
|
|
3c4c65c28c | ||
|
|
15885e3e8c | ||
|
|
5508c60e85 | ||
|
|
ffc341e4b9 | ||
|
|
41a68f7b25 | ||
|
|
041d3c5312 | ||
|
|
8e8b462bc8 | ||
|
|
efbc76e06f | ||
|
|
67a44d2adc | ||
|
|
92a35b929a | ||
|
|
e5744dd63f | ||
|
|
f2f3d050bd | ||
|
|
0cbecbe3a0 | ||
|
|
51a8b5a058 | ||
|
|
aaf716e54b | ||
|
|
209fcc7946 | ||
|
|
a5cb131806 | ||
|
|
8fbeb5f5d5 | ||
|
|
a92bdfe30d | ||
|
|
7f130ff036 | ||
|
|
b704f72854 | ||
|
|
e21f8a97ac | ||
|
|
a8ff403809 | ||
|
|
22097c0a25 | ||
|
|
92e7d9cf80 | ||
|
|
54d921f275 | ||
|
|
08d7b3dbce | ||
|
|
6949b3c229 | ||
|
|
b0ca38bd29 | ||
|
|
cf173ee9e7 | ||
|
|
aa9908b34a | ||
|
|
640674ef72 | ||
|
|
0c69ab80bb | ||
|
|
662557c2f3 | ||
|
|
346b2c31d2 | ||
|
|
62dbf99557 | ||
|
|
99b140adaa | ||
|
|
387d577d4f | ||
|
|
ab7eee7db9 | ||
|
|
487a45f01b | ||
|
|
60665c6bd8 | ||
|
|
8fc9a3d6d1 | ||
|
|
05a05f7e88 | ||
|
|
0c5bdfd7b7 | ||
|
|
626e93c7e3 | ||
|
|
b588c4c900 | ||
|
|
c52a0d88df | ||
|
|
84838d19d9 | ||
|
|
faf335a181 | ||
|
|
5c25351884 | ||
|
|
520f3cb09a | ||
|
|
e234246618 | ||
|
|
5d1d378f61 | ||
|
|
cef3bb7424 | ||
|
|
ccb03f2763 | ||
|
|
1f6168366b | ||
|
|
cd5bf85245 | ||
|
|
f2778e5d28 | ||
|
|
c2e6065ed7 | ||
|
|
fccba5f7fd | ||
|
|
3f230c5a05 | ||
|
|
dc849c3891 | ||
|
|
2770b58a20 | ||
|
|
37519acfb8 | ||
|
|
ad8c7b3cd2 | ||
|
|
04db8d3208 | ||
|
|
666e3b1e30 | ||
|
|
dc68781c06 | ||
|
|
a7f50d147e | ||
|
|
7e639db5de | ||
|
|
19a97a1706 | ||
|
|
cd66a9ef61 | ||
|
|
f121430a5d | ||
|
|
2f518dacfc | ||
|
|
fded8b6cd3 | ||
|
|
3b6c64dc9d | ||
|
|
d742985640 | ||
|
|
a13dd58989 | ||
|
|
622b3210ae | ||
|
|
90c97ed6aa | ||
|
|
53a4dfbf88 | ||
|
|
f488c57363 | ||
|
|
0ce830ca9d | ||
|
|
30ae418c2c | ||
|
|
3b976d211f | ||
|
|
cca49b5dc2 | ||
|
|
8c2b2070c6 | ||
|
|
24b8ff26db | ||
|
|
f0d93538ae | ||
|
|
02eab65c4e | ||
|
|
d941aa7df3 | ||
|
|
b5026a45f6 | ||
|
|
79fde3ebc9 | ||
|
|
031d648585 | ||
|
|
762b2fe7d6 | ||
|
|
5db377923e | ||
|
|
c3177df739 | ||
|
|
0dc36765f1 | ||
|
|
38e61ebd8d | ||
|
|
529b9739b5 | ||
|
|
a014ca7d8a | ||
|
|
83701f7d0d | ||
|
|
b2500939f3 | ||
|
|
1852b9dbb2 | ||
|
|
069474fc71 | ||
|
|
e7f518264a | ||
|
|
b0b096c3f5 | ||
|
|
bfa9d04d42 | ||
|
|
7dbe58469a | ||
|
|
41b36dabc2 | ||
|
|
4a685557d9 | ||
|
|
e7ef4b6906 | ||
|
|
67502fb9d3 | ||
|
|
960283bdcf | ||
|
|
39f30eab7a | ||
|
|
24b4741aaf | ||
|
|
64f373fb43 | ||
|
|
bc1830d8eb | ||
|
|
f2a2a91682 | ||
|
|
274ac339ad | ||
|
|
1d916286ee | ||
|
|
832d54300a | ||
|
|
ba6d3bbe15 | ||
|
|
c1d0789ac7 | ||
|
|
0573d0083e | ||
|
|
e57d62b682 | ||
|
|
bb6f27b322 | ||
|
|
86f424ad37 | ||
|
|
ad81bbc761 | ||
|
|
07e868e6f6 | ||
|
|
b45700df03 | ||
|
|
93ce2a8e3a | ||
|
|
fbc4d46962 | ||
|
|
d73d138b3f | ||
|
|
14ea21d53d | ||
|
|
2b3791b83e | ||
|
|
e04809f96b | ||
|
|
9203acff9c | ||
|
|
afc1a9f077 | ||
|
|
fc57851113 | ||
|
|
1f1d3f843f | ||
|
|
b389260dec | ||
|
|
1f37a5ff8f | ||
|
|
815d60eca2 | ||
|
|
877a584a26 | ||
|
|
0c60c9ff75 | ||
|
|
6a7a868b71 | ||
|
|
b5a070b228 | ||
|
|
39f13c6e5b | ||
|
|
8c98da09f0 | ||
|
|
ed70a7200c | ||
|
|
ea4410cd16 | ||
|
|
9d9b1cbcd5 | ||
|
|
f17d8f38fb | ||
|
|
0efc9d1cd2 | ||
|
|
4f5d5f1afd | ||
|
|
c4d8d7abf4 | ||
|
|
3fad29a709 | ||
|
|
665f204c1f | ||
|
|
362b651823 | ||
|
|
49b56588b8 | ||
|
|
c7a763ffdc | ||
|
|
5435ddad9f | ||
|
|
0ecd466c4c | ||
|
|
6117e25b97 | ||
|
|
ee10f09bc6 | ||
|
|
58512e302f | ||
|
|
ce564c209b | ||
|
|
7296d49693 | ||
|
|
290fdc4c0f | ||
|
|
1fa5ae695d | ||
|
|
b2ba6d38b8 | ||
|
|
620f1b94bc | ||
|
|
c8fb5d1a9a | ||
|
|
1f763aeb72 | ||
|
|
fcfb019555 | ||
|
|
d4c1acb126 | ||
|
|
862bf43685 | ||
|
|
f83139a9ee | ||
|
|
3d938b3edf | ||
|
|
6c6ae66e36 | ||
|
|
813e423bec | ||
|
|
a9a235fc87 | ||
|
|
6e1c6b4bed | ||
|
|
2214059a63 | ||
|
|
424cfcfa0c | ||
|
|
ce871dfa3e | ||
|
|
48a6eb1f86 | ||
|
|
fb85fb5b76 | ||
|
|
c39c3cfdae | ||
|
|
e2fa7c666a | ||
|
|
f49cc6fb1f | ||
|
|
69bef59473 | ||
|
|
9e931b9eb0 | ||
|
|
b26d9ea1e0 | ||
|
|
ca5607d79e | ||
|
|
903eaed250 | ||
|
|
0859eab2dc | ||
|
|
f0f84722ba | ||
|
|
17b8ba7069 | ||
|
|
eb91152cfa | ||
|
|
08c1b6879e | ||
|
|
0077a8f67c | ||
|
|
a89cc67bd2 | ||
|
|
388415ecc2 | ||
|
|
44c5ba208d | ||
|
|
d3a51857cb | ||
|
|
11a3db5d64 | ||
|
|
f3be8ae608 | ||
|
|
0577c9121c | ||
|
|
058f51e8c1 | ||
|
|
698444caec | ||
|
|
d575df4b19 | ||
|
|
bee98513a2 | ||
|
|
3746df49ee | ||
|
|
d98f67eab9 | ||
|
|
fde415e251 | ||
|
|
5702f39181 | ||
|
|
45658afd89 | ||
|
|
ece4a51b94 | ||
|
|
837d4918f2 | ||
|
|
57ae0f1676 | ||
|
|
48e644e007 | ||
|
|
49a04fa913 | ||
|
|
df943bcf75 | ||
|
|
fdbec176fa | ||
|
|
4b2b4e5482 | ||
|
|
96768d8529 | ||
|
|
2689a08026 | ||
|
|
54be70672e | ||
|
|
480fa50af5 | ||
|
|
b51731d15f | ||
|
|
c09650a136 | ||
|
|
769fcb20d8 | ||
|
|
537c4b3a50 | ||
|
|
a75c17ac5e | ||
|
|
85604e8afa | ||
|
|
9a45c9aa7c | ||
|
|
01450bacc2 | ||
|
|
af0255ee09 | ||
|
|
df25bbb6d2 | ||
|
|
444685bc05 | ||
|
|
115f63c330 | ||
|
|
f9dbc4f7bf | ||
|
|
83263f8dee | ||
|
|
a452ade957 | ||
|
|
1f48af024e | ||
|
|
0a643d7195 | ||
|
|
c3835b9da7 | ||
|
|
bb1a96cf7a | ||
|
|
56360301d7 | ||
|
|
435cccdeae | ||
|
|
b11b472933 | ||
|
|
514f8398e2 | ||
|
|
90935fef25 | ||
|
|
9b5ce1c3a6 | ||
|
|
8ad1639b02 | ||
|
|
6d70332cd6 | ||
|
|
717f6240e3 | ||
|
|
ab782054a1 | ||
|
|
b481f01217 | ||
|
|
d0f884f5b2 | ||
|
|
51e66354b0 | ||
|
|
1efe90f445 | ||
|
|
7b47b7549d | ||
|
|
7ccb77fb57 | ||
|
|
a32fa69823 | ||
|
|
ece4cb03ad | ||
|
|
5c53b6528f | ||
|
|
9b92007eff | ||
|
|
e433809f4d | ||
|
|
d74218004a | ||
|
|
c35276e3df | ||
|
|
064236ed5b | ||
|
|
2a50dcba9d | ||
|
|
f7974b324b | ||
|
|
3bb716b060 | ||
|
|
39e465261f | ||
|
|
784b78b17c | ||
|
|
22c68ed8ef | ||
|
|
c4c670a3b1 | ||
|
|
17a05cc1d4 | ||
|
|
d452c5fabb | ||
|
|
2cf974ef02 | ||
|
|
1f0e789575 | ||
|
|
92e1fd3f28 | ||
|
|
49736a87aa | ||
|
|
d009e39842 | ||
|
|
c2b8901537 | ||
|
|
dd910cb5ec | ||
|
|
4632753f02 | ||
|
|
3fdcd12b4f | ||
|
|
94d1d611c7 | ||
|
|
27b54a0bfa | ||
|
|
1b1ecd0748 | ||
|
|
1e29d2e751 | ||
|
|
a0437bf933 | ||
|
|
73e0292a4b | ||
|
|
c393e74160 | ||
|
|
80c4666198 | ||
|
|
ea7bd1f700 | ||
|
|
b3a55cc85d | ||
|
|
036200350d | ||
|
|
e630c484ff | ||
|
|
713e9658c5 | ||
|
|
782039810e | ||
|
|
b473d8ab9c | ||
|
|
2eb6918fb3 | ||
|
|
29626666a7 | ||
|
|
dc41c9a671 | ||
|
|
83af70bb59 | ||
|
|
b293873640 | ||
|
|
8bb92815cb | ||
|
|
7a8f7199c8 | ||
|
|
6f4ce34840 | ||
|
|
8853552161 | ||
|
|
95d3d17d83 | ||
|
|
3594280b04 | ||
|
|
1e447c6e3e | ||
|
|
c41a288280 | ||
|
|
a0492fe944 | ||
|
|
1fffebd497 | ||
|
|
62c05049a7 | ||
|
|
0fdf377d45 | ||
|
|
6ca8e2644a | ||
|
|
4a3061db6d | ||
|
|
61ac81518a | ||
|
|
acd4b4371d | ||
|
|
1d20291d44 | ||
|
|
c60245ea2b | ||
|
|
9e25480baa | ||
|
|
facd803943 | ||
|
|
05c8a6282d | ||
|
|
3f9ae34203 | ||
|
|
afb85309a2 | ||
|
|
2c5e64d0d5 | ||
|
|
ddb8c432be | ||
|
|
054be314f6 | ||
|
|
e484c5754e | ||
|
|
b36c4f65e5 | ||
|
|
4bdfbcc916 | ||
|
|
519198bb61 | ||
|
|
9a7c342f91 | ||
|
|
761a5ed3dd | ||
|
|
481e753ad4 | ||
|
|
271016f0fa | ||
|
|
4493f895c6 | ||
|
|
5c32ecd8e1 | ||
|
|
0b5244d321 | ||
|
|
b6f9715174 | ||
|
|
2db1f8d2b6 | ||
|
|
4c5957ae40 | ||
|
|
38cd19de15 | ||
|
|
f66ffbdd63 | ||
|
|
8d3f08e529 | ||
|
|
4209c1c406 | ||
|
|
1cd12d0a0c | ||
|
|
7eb18e1931 | ||
|
|
d308e50e1e | ||
|
|
88569cb369 | ||
|
|
235869fc79 | ||
|
|
89166e81fb | ||
|
|
2d109b81cf | ||
|
|
5c02b4dccb | ||
|
|
e7f154b58d | ||
|
|
c0752575c6 | ||
|
|
7eb2c89f39 | ||
|
|
bf4eb07342 | ||
|
|
c856d01b52 | ||
|
|
7a535b2576 | ||
|
|
4b17fd88a3 | ||
|
|
8d1f3f723f | ||
|
|
a543fbbec9 | ||
|
|
37f50db00e | ||
|
|
ccb87f43b7 | ||
|
|
d569f39f53 | ||
|
|
fb3951772f | ||
|
|
2c00bf4040 | ||
|
|
4f8772bd77 | ||
|
|
b4c3046ab5 | ||
|
|
2441b92bc6 | ||
|
|
c39eec32f2 | ||
|
|
7837718d04 | ||
|
|
7069671471 | ||
|
|
d1dbde2890 | ||
|
|
0472471ac9 | ||
|
|
62a0b8da90 | ||
|
|
810530fabd | ||
|
|
707de56612 | ||
|
|
921b0eb229 | ||
|
|
9afb92f0ed | ||
|
|
1ded88e089 | ||
|
|
1f074ff400 | ||
|
|
4764f61b48 | ||
|
|
56424924bb | ||
|
|
4c3831ec74 | ||
|
|
ba564a6aed |
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.html linguist-documentation
|
||||
(^|/)site/) linguist-documentation
|
||||
34
.github/contributing.md
vendored
Normal file
34
.github/contributing.md
vendored
Normal 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
20
.github/issue_template.md
vendored
Normal 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
9
.github/pull_request_template.md
vendored
Normal 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*
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
*/target/**
|
||||
# IntelliJ test run side-effects
|
||||
dependency-check-core/data/
|
||||
dependency-check-ant/data/
|
||||
# Intellij project files
|
||||
*.iml
|
||||
*.ipr
|
||||
@@ -15,6 +16,7 @@ maven-eclipse.xml
|
||||
.pmd
|
||||
# Netbeans configuration
|
||||
nb-configuration.xml
|
||||
**/nbproject/
|
||||
/target/
|
||||
#maven-shade-plugin generated pom
|
||||
dependency-reduced-pom.xml
|
||||
@@ -26,3 +28,5 @@ _site/**
|
||||
.LCKpom.xml~
|
||||
#coverity
|
||||
/cov-int/
|
||||
/dependency-check-core/nbproject/
|
||||
cov-scan.bat
|
||||
|
||||
66
.travis.settings.xml
Normal file
66
.travis.settings.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<servers>
|
||||
<server>
|
||||
<username>${env.JFROG_USER}</username>
|
||||
<password>${env.JFROG_PASSWORD}</password>
|
||||
<id>release</id>
|
||||
</server>
|
||||
<server>
|
||||
<username>${env.JFROG_USER}</username>
|
||||
<password>${env.JFROG_PASSWORD}</password>
|
||||
<id>snapshot</id>
|
||||
</server>
|
||||
<server>
|
||||
<username>${env.JFROG_USER}</username>
|
||||
<password>${env.JFROG_PASSWORD}</password>
|
||||
<id>plugins-release</id>
|
||||
</server>
|
||||
<server>
|
||||
<username>${env.JFROG_USER}</username>
|
||||
<password>${env.JFROG_PASSWORD}</password>
|
||||
<id>plugins-snapshot</id>
|
||||
</server>
|
||||
</servers>
|
||||
<profiles>
|
||||
<profile>
|
||||
<repositories>
|
||||
<repository>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<id>release</id>
|
||||
<name>libs-release</name>
|
||||
<url>https://dependencycheck.jfrog.io/dependencycheck/libs-release</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<snapshots />
|
||||
<id>snapshot</id>
|
||||
<name>libs-snapshot</name>
|
||||
<url>https://dependencycheck.jfrog.io/dependencycheck/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<id>plugins-release</id>
|
||||
<name>plugins-release</name>
|
||||
<url>https://dependencycheck.jfrog.io/dependencycheck/plugins-release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<snapshots />
|
||||
<id>plugins-snapshot</id>
|
||||
<name>plugins-snapshot</name>
|
||||
<url>https://dependencycheck.jfrog.io/dependencycheck/plugins-snapshot</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<id>artifactory</id>
|
||||
</profile>
|
||||
</profiles>
|
||||
<activeProfiles>
|
||||
<activeProfile>artifactory</activeProfile>
|
||||
</activeProfiles>
|
||||
</settings>
|
||||
78
.travis.yml
Normal file
78
.travis.yml
Normal file
@@ -0,0 +1,78 @@
|
||||
language: java
|
||||
sudo: required
|
||||
group: deprecated-2017Q4
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "ZUzhWfpXJw/oAeDlUkDFkEJMT0T7kCN3d7ah8urkL2B0KFfKOqQagkbXkgvDa1SYud8VdcnoGa69LfkEr5IrdqW7R4bEYZAiN5swm4Z0iO8t53szVspm2f+O9jQ44O/sfOfpfLxWUUuhdc7Vbrszp+tSszxdPmssWL+f5a/mfWs="
|
||||
- secure: "pmFymoI7qH0Kna3NkcHrqLiTVWKmrhwqA4Z9U6XLhWDQxcs5g94wCCKpGB6Lkz9mkvRxBRFpZZelnXJa9W9mnuVOMIa5tQfS5gBuaNXOe7AXXdc+Y2975OR9sSfvf16FxLFvNJILmZq+bpMLs+EXaQvjYQHW2O6OWZdLhAPVG6A="
|
||||
- secure: "omj5HP2wKdegLYp8/a24Wsoryb92+XYWheEkxp7CzHGDJB1Y4SSr315n/na/mdgd7lr1Ac+m4stYfCrclG7be71xWs6ApF+6I5QSzplJ1fyIF5piHrmhgw6ymIf/HBdeevggJM8igD8agCOwEETYFKfPEj5wFWhNQfxYwANbpl0="
|
||||
- secure: "FqPcda7a6rEvGVYEyWeaFP+mIhZeJ6FGSdHvVRlBL0H9I3bz6eZg50g6DH3yo1bkmTPQ94eXdDpoKihk9+CDLl0TS+Sg9W8HplG3B2U1/6Yi3vd0T8yjKZC7xf0VZO6t8AT9vpFvzQBRZe24n+6kDtp2OiBzawJhgU5t09zH6is="
|
||||
- secure: "Bh5LAk8XQnJ885jc/Lli2fhPKDx0TNZRxcJMnNo96EgwOnD+Zhw+v3u/DMCgyyrRToM8Bkca/HktrlZaRTk2htsdKZZ3RHFMCXO0fXCgpcf+wkaSYDF/lnErpSJG3Lrz8ILxJPODsrGhjaIg2++79lwhsBYtpujc6UdxFhgpffc="
|
||||
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "odc"
|
||||
token:
|
||||
secure: "YVDnYmonPug885Hmr2pLWBko+rQ+oKyTUA95ry0PGGyfgs0z6kPCjmWBDVm7K4GM7NOluldWb5gLMf0QXoHGstdp9L6fQCQElt8hZMOwJf+IR3bWjiG3VfVyyB3gJWBWlcJFM9NVyfICidwBH5ZiJ0+LXhKUgnNqarTh/YmNj9w="
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- "$HOME/.m2/repository"
|
||||
- "$HOME/.sonar/cache"
|
||||
|
||||
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)
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- jdk: openjdk7
|
||||
env:
|
||||
- JDK="JDK7"
|
||||
script:
|
||||
- if [ ! -z "$TRAVIS_TAG" ]; then travis_wait 60 mvn install site site:stage -DreleaseTesting; else travis_wait 60 mvn install -DreleaseTesting; fi
|
||||
- jdk: oraclejdk8
|
||||
env:
|
||||
- JDK="JDK8"
|
||||
script:
|
||||
- travis_wait 60 mvn install -DreleaseTesting
|
||||
|
||||
after_success:
|
||||
- if [ "$JDK" == "JDK8" ]; then
|
||||
java -cp ~/codacy-coverage-reporter-assembly-latest.jar com.codacy.CodacyCoverageReporter -l Java -r build-reporting/target/coverage-reports/jacoco.xml;
|
||||
mvn sonar:sonar -Dsonar.java.coveragePlugin=jacoco -Dsonar.jacoco.reportPath=build-reporting/target/jacoco.xml;
|
||||
./coverity_scan.sh;
|
||||
fi;
|
||||
|
||||
after_failure:
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/617-hierarchical-cross-deps/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/618-aggregator-purge/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/618-aggregator-update-only/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/629-jackson-dataformat/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/690-threadsafety/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/710-pom-parse-error/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/729-system-scope-resolved/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/729-system-scope-skipped/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/730-multiple-suppression-files/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/730-multiple-suppression-files-configs/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/815-broken-suppression-aggregate/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/846-site-plugin/build.log
|
||||
- cat /home/travis/build/jeremylong/DependencyCheck/dependency-check-maven/target/it/false-positives/build.log
|
||||
|
||||
deploy:
|
||||
- provider: script
|
||||
script: mvn --settings .travis.settings.xml source:jar javadoc:jar package deploy -DskipTests=true
|
||||
skip_cleanup: true
|
||||
on:
|
||||
branch: master
|
||||
jdk: openjdk7
|
||||
- provider: pages
|
||||
skip_cleanup: true
|
||||
local_dir: target/staging
|
||||
github_token: $GITHUB_TOKEN
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
jdk: openjdk7
|
||||
|
||||
36
Dockerfile
Normal file
36
Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
FROM openjdk:8-jre-slim
|
||||
|
||||
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 apt-get update && \
|
||||
apt-get install -y --no-install-recommends wget ruby mono-runtime && \
|
||||
gem install bundle-audit && \
|
||||
gem cleanup
|
||||
|
||||
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/ && \
|
||||
useradd -ms /bin/bash ${user} && \
|
||||
chown -R ${user}:${user} /usr/share/dependency-check && \
|
||||
mkdir /report && \
|
||||
chown -R ${user}:${user} /report && \
|
||||
apt-get remove --purge -y wget && \
|
||||
apt-get autoremove -y && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/*
|
||||
|
||||
USER ${user}
|
||||
|
||||
VOLUME ["/src" "/usr/share/dependency-check/data" "/report"]
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
CMD ["--help"]
|
||||
ENTRYPOINT ["/usr/share/dependency-check/bin/dependency-check.sh"]
|
||||
180
README.md
180
README.md
@@ -1,3 +1,7 @@
|
||||
[](https://travis-ci.org/jeremylong/DependencyCheck) [](https://scan.coverity.com/projects/dependencycheck) [](https://www.codacy.com/app/jeremylong/DependencyCheck?utm_source=github.com&utm_medium=referral&utm_content=jeremylong/DependencyCheck&utm_campaign=Badge_Grade) [](https://bestpractices.coreinfrastructure.org/projects/843) [](https://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
|
||||
[](https://www.toolswatch.org/2015/06/black-hat-arsenal-usa-2015-speakers-lineup/) [](https://www.toolswatch.org/2014/06/black-hat-usa-2014-arsenal-tools-speaker-list/) [](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,24 +25,27 @@ 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).
|
||||
The plugin can be configured using the following:
|
||||
More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven).
|
||||
By default, the plugin is tied to the `verify` phase (i.e. `mvn verify`). Alternatively,
|
||||
one can directly invoke the plugin via `mvn org.owasp:dependency-check-maven:check`.
|
||||
|
||||
The dependency-check plugin can be configured using the following:
|
||||
|
||||
```xml
|
||||
<project>
|
||||
@@ -66,7 +73,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,16 +91,157 @@ 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.
|
||||
Then load the resulting 'dependency-check-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"
|
||||
|
||||
```
|
||||
|
||||
|
||||
Upgrade Notes
|
||||
-------------
|
||||
|
||||
### Upgrading from **1.x.x** to **2.x.x**
|
||||
|
||||
Note that when upgrading from version 1.x.x that the following changes will need to be made to your configuration.
|
||||
|
||||
#### Suppression file
|
||||
|
||||
In order to support multiple suppression files, the mechanism for configuring suppression files has changed.
|
||||
As such, users that have defined a suppression file in their configuration will need to update.
|
||||
|
||||
See the examples below:
|
||||
|
||||
##### Ant
|
||||
|
||||
Old:
|
||||
|
||||
```xml
|
||||
<dependency-check
|
||||
failBuildOnCVSS="3"
|
||||
suppressionFile="suppression.xml">
|
||||
</dependency-check>
|
||||
```
|
||||
|
||||
New:
|
||||
|
||||
```xml
|
||||
<dependency-check
|
||||
failBuildOnCVSS="3">
|
||||
<suppressionFile path="suppression.xml" />
|
||||
</dependency-check>
|
||||
```
|
||||
|
||||
##### Maven
|
||||
|
||||
Old:
|
||||
|
||||
```xml
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<configuration>
|
||||
<suppressionFile>suppression.xml</suppressionFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
New:
|
||||
|
||||
```xml
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<configuration>
|
||||
<suppressionFiles>
|
||||
<suppressionFile>suppression.xml</suppressionFile>
|
||||
</suppressionFiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
### Gradle
|
||||
|
||||
In addition to the changes to the suppression file, the task `dependencyCheck` has been
|
||||
renamed to `dependencyCheckAnalyze`.
|
||||
|
||||
Old:
|
||||
|
||||
```groovy
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'org.owasp:dependency-check-gradle:2.0.1-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
apply plugin: 'org.owasp.dependencycheck'
|
||||
|
||||
dependencyCheck {
|
||||
suppressionFile='path/to/suppression.xml'
|
||||
}
|
||||
check.dependsOn dependencyCheckAnalyze
|
||||
```
|
||||
|
||||
New:
|
||||
```groovy
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'org.owasp:dependency-check-gradle:2.0.1-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
apply plugin: 'org.owasp.dependencycheck'
|
||||
|
||||
dependencyCheck {
|
||||
suppressionFiles = ['path/to/suppression1.xml', 'path/to/suppression2.xml']
|
||||
}
|
||||
check.dependsOn dependencyCheckAnalyze
|
||||
```
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
@@ -107,14 +255,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-2017 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
|
||||
|
||||
61
RELEASE_NOTES.md
Normal file
61
RELEASE_NOTES.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Release Notes
|
||||
|
||||
Please see the [dependency-check google group](https://groups.google.com/forum/#!forum/dependency-check) for the release notes on versions not listed below.
|
||||
|
||||
## [Version 3.1.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.1.1) (2018-01-29)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Fixed the Central Analyzer to use the updated SHA1 query syntax.
|
||||
- Reverted change that broke Maven 3.1.0 compatability; Maven 3.1.0 and beyond is once again supported.
|
||||
- False positive reduction.
|
||||
- Minor documentation cleanup.
|
||||
|
||||
|
||||
## [Version 3.1.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.1.0) (2018-01-02)
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Major enhancements to the Node and NSP analyzer - the analyzers are now considered
|
||||
production ready and should be used in combination.
|
||||
- Added a shutdown hook so that if the update process is interrupted while using an H2
|
||||
database the lock files will be properly removed allowing future executions of ODC to
|
||||
succeed.
|
||||
- UNC paths can now be scanned using the CLI.
|
||||
- Batch updates are now used which may help with the update speed when using some DBMS
|
||||
instead of the embedded H2.
|
||||
- Upgrade Lucene to 5.5.5, the highest version that will allow us to maintain Java 7 support
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Fixed the CSV report output to correctly list all fields.
|
||||
- Invalid suppression files will now break the build instead of causing ODC to
|
||||
skip the usage of the suppression analyzer.
|
||||
- Fixed bug in Lucene query where LARGE entries in the pom.xml or manifest caused
|
||||
the query to break.
|
||||
- General cleanup, false positive, and false negative reduction.
|
||||
|
||||
## [Version 3.0.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.0.2) (2017-11-13)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Updated the query format for the CentralAnalyzer; the old format caused the CentralAnalyzer to fail
|
||||
|
||||
## [Version 3.0.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.0.1) (2017-10-20)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Fixed a database connection issue that affected some usages.
|
||||
|
||||
## [Version 3.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.0.0) (2017-10-16)
|
||||
|
||||
- Several bug fixes and false positive reduction
|
||||
- The 2.x branch introduced several new false positives – but also reduced the false negatives
|
||||
- Java 9 compatibility update
|
||||
- Stability issues with the Central Analyzer resolved
|
||||
- This comes at a cost of a longer analysis time
|
||||
- The CSV report now includes the GAV and CPE
|
||||
- The Hint Analyzer now supports regular expressions
|
||||
- If show summary is disabled and vulnerable libraries are found that fail the build details are no longer displayed in the console – only that vulnerable libraries were identified
|
||||
- Resolved issues with threading and multiple connections to the embedded H2 database
|
||||
- This allows the Jenkins pipeline, Maven Plugin, etc. to safely run parallel executions of dependency-check
|
||||
@@ -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.
|
||||
|
||||
-----------------------------
|
||||
@@ -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.
|
||||
@@ -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>3.1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-ant</artifactId>
|
||||
@@ -28,15 +28,6 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
||||
|
||||
<name>Dependency-Check Ant Task</name>
|
||||
<description>dependency-check-ant is an Ant Task that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the project's dependencies. The task will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
|
||||
<!-- 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}/dependency-check-ant</url>
|
||||
</site>
|
||||
</distributionManagement>
|
||||
<!-- end copy -->
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
@@ -190,218 +181,41 @@ 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>
|
||||
<version>${reporting.checkstyle-plugin.version}</version>
|
||||
<configuration>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
<enableFilesSummary>false</enableFilesSummary>
|
||||
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
|
||||
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
|
||||
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>${reporting.pmd-plugin.version}</version>
|
||||
<configuration>
|
||||
<targetJdk>1.6</targetJdk>
|
||||
<linkXref>true</linkXref>
|
||||
<sourceEncoding>utf-8</sourceEncoding>
|
||||
<excludes>
|
||||
<exclude>**/generated/*.java</exclude>
|
||||
</excludes>
|
||||
<rulesets>
|
||||
<ruleset>../src/main/config/dcrules.xml</ruleset>
|
||||
<ruleset>/rulesets/java/basic.xml</ruleset>
|
||||
<ruleset>/rulesets/java/imports.xml</ruleset>
|
||||
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
|
||||
</rulesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>${reporting.findbugs-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.owasp</groupId>
|
||||
@@ -423,6 +237,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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
1183
ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
Normal file
1183
ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
Normal file
File diff suppressed because it is too large
Load Diff
174
ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
Normal file
174
ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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";
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private Settings settings;
|
||||
|
||||
/**
|
||||
* The location of the data directory that contains
|
||||
*/
|
||||
private String dataDirectory = null;
|
||||
/**
|
||||
* Indicates if dependency-check should fail the build if an exception
|
||||
* occurs.
|
||||
*/
|
||||
private boolean failOnError = true;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 exist: %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 = new Settings();
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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) 2017 The OWASP Foundation. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.taskdefs;
|
||||
|
||||
/**
|
||||
* Class : {@link SuppressionFile} Responsibility : Models a suppression file
|
||||
* nested XML element where the simple content is its location.
|
||||
*
|
||||
* @author Phillip Whittlesea
|
||||
*/
|
||||
public class SuppressionFile {
|
||||
|
||||
/**
|
||||
* The path to the suppression file.
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* Sets the path to the suppression file.
|
||||
*
|
||||
* @param path the path to the suppression file
|
||||
*/
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to the suppression file.
|
||||
*
|
||||
* @return the path
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
438
ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
Normal file
438
ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* 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();
|
||||
try (Engine engine = new Engine(Update.class.getClassLoader(), getSettings())) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUsername);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
|
||||
getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
|
||||
if (cveValidForHours != null) {
|
||||
if (cveValidForHours >= 0) {
|
||||
getSettings().setInt(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
|
||||
} else {
|
||||
throw new BuildException("Invalid setting: `cpeValidForHours` must be 0 or greater");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,33 +23,35 @@ 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.
|
||||
*
|
||||
* @return the StaticLoggerBinder singleton
|
||||
*/
|
||||
public static final StaticLoggerBinder getSingleton() {
|
||||
public static StaticLoggerBinder getSingleton() {
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
2
ant/src/main/resources/task.properties
Normal file
2
ant/src/main/resources/task.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
# the path to the data directory
|
||||
data.directory=data/3.0
|
||||
20
ant/src/site/markdown/config-purge.md
Normal file
20
ant/src/site/markdown/config-purge.md
Normal 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
|
||||
45
ant/src/site/markdown/config-update.md
Normal file
45
ant/src/site/markdown/config-update.md
Normal 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. |
|
||||
proxyPort | The Proxy Port. |
|
||||
proxyUsername | Defines the proxy user name. |
|
||||
proxyPassword | Defines the proxy password. |
|
||||
connectionTimeout | The URL Connection Timeout. |
|
||||
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. |
|
||||
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |
|
||||
connectionString | The connection string used to connect to the database. |
|
||||
databaseUser | The username used when connecting to the database. |
|
||||
databasePassword | The password used when connecting to the database. |
|
||||
107
ant/src/site/markdown/configuration.md
Normal file
107
ant/src/site/markdown/configuration.md
Normal file
@@ -0,0 +1,107 @@
|
||||
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),
|
||||
or [FileList](http://ant.apache.org/manual/Types/filelist.html) that includes
|
||||
the project's dependencies.
|
||||
|
||||
```xml
|
||||
<target name="dependency-check" description="Dependency-Check Analysis">
|
||||
<dependency-check projectname="Hello World"
|
||||
reportoutputdirectory="${basedir}"
|
||||
reportformat="ALL">
|
||||
<suppressionfile path="${basedir}/path/to/suppression.xml" />
|
||||
<fileset dir="lib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</dependency-check>
|
||||
</target>
|
||||
```
|
||||
|
||||
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
|
||||
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 equal to or 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'
|
||||
hintsFile | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) |
|
||||
proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. |
|
||||
proxyPort | The Proxy Port. |
|
||||
proxyUsername | Defines the proxy user name. |
|
||||
proxyPassword | Defines the proxy password. |
|
||||
connectionTimeout | The URL Connection Timeout. |
|
||||
enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false
|
||||
enableRetired | Enable the [retired analyzers](../analyzers/index.html). If not enabled the retired analyzers (see below) will not be loaded or used. | false
|
||||
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). |
|
||||
|
||||
The following nested elements can be set on the dependency-check task.
|
||||
|
||||
Element | Property | Description | Default Value
|
||||
------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------
|
||||
suppressionFile | path | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). Element can be specified multiple times. |
|
||||
|
||||
Analyzer Configuration
|
||||
====================
|
||||
The following properties are used to configure the various file type analyzers.
|
||||
These properties can be used to turn off specific analyzers if it is not needed.
|
||||
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. |
|
||||
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 (requires Nexus Pro). 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. |
|
||||
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 [retired](../analyzers/index.html) Node.js Analyzer should be used. | true
|
||||
nspAnalyzerEnabled | Sets whether the NSP 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. |
|
||||
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. |
|
||||
|
||||
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. | http://nvd.nist.gov/download/nvdcve-modified.xml
|
||||
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 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. |
|
||||
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |
|
||||
connectionString | The connection string used to connect to the database. |
|
||||
databaseUser | The username used when connecting to the database. |
|
||||
databasePassword | The password used when connecting to the database. |
|
||||
38
ant/src/site/markdown/index.md.vm
Normal file
38
ant/src/site/markdown/index.md.vm
Normal file
@@ -0,0 +1,38 @@
|
||||
About
|
||||
====================
|
||||
OWASP dependency-check-ant is an Ant Task that uses dependency-check-core to detect publicly
|
||||
disclosed vulnerabilities associated with the project's dependencies. The task will
|
||||
generate a report listing the dependency, any identified Common Platform Enumeration (CPE)
|
||||
identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.
|
||||
|
||||
Installation
|
||||
====================
|
||||
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
|
||||
<!-- 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.
|
||||
|
||||
|
||||
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
|
||||
Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov
|
||||
|
||||
After the first batch download, as long as the task is executed at least once every
|
||||
seven days the update will only take a few seconds.
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -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" />
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.taskdefs;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.BuildFileRule;
|
||||
import org.apache.tools.ant.types.LogLevel;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.owasp.dependencycheck.BaseDBTestCase;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class DependencyCheckTaskTest extends BaseDBTestCase {
|
||||
|
||||
@Rule
|
||||
public BuildFileRule buildFileRule = new BuildFileRule();
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
final String buildFile = this.getClass().getClassLoader().getResource("build.xml").getPath();
|
||||
buildFileRule.configureProject(buildFile, LogLevel.VERBOSE.getLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of addFileSet method, of class DependencyCheckTask.
|
||||
*/
|
||||
@Test
|
||||
public void testAddFileSet() throws Exception {
|
||||
File report = new File("target/dependency-check-report.html");
|
||||
if (report.exists() && !report.delete()) {
|
||||
throw new Exception("Unable to delete 'target/dependency-check-report.html' prior to test.");
|
||||
}
|
||||
buildFileRule.executeTarget("test.fileset");
|
||||
assertTrue("DependencyCheck report was not generated", report.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of addFileList method, of class DependencyCheckTask.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testAddFileList() throws Exception {
|
||||
File report = new File("target/dependency-check-report.xml");
|
||||
if (report.exists()) {
|
||||
if (!report.delete()) {
|
||||
throw new Exception("Unable to delete 'target/DependencyCheck-Report.xml' prior to test.");
|
||||
}
|
||||
}
|
||||
buildFileRule.executeTarget("test.filelist");
|
||||
|
||||
assertTrue("DependencyCheck report was not generated", report.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of addDirSet method, of class DependencyCheckTask.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testAddDirSet() throws Exception {
|
||||
File report = new File("target/dependency-check-vulnerability.html");
|
||||
if (report.exists()) {
|
||||
if (!report.delete()) {
|
||||
throw new Exception("Unable to delete 'target/DependencyCheck-Vulnerability.html' prior to test.");
|
||||
}
|
||||
}
|
||||
buildFileRule.executeTarget("test.dirset");
|
||||
assertTrue("DependencyCheck report was not generated", report.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getFailBuildOnCVSS method, of class DependencyCheckTask.
|
||||
*/
|
||||
@Test
|
||||
public void testGetFailBuildOnCVSS() {
|
||||
expectedException.expect(BuildException.class);
|
||||
buildFileRule.executeTarget("failCVSS");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the DependencyCheckTask where a CVE is suppressed.
|
||||
*/
|
||||
@Test
|
||||
public void testSuppressingCVE() {
|
||||
// GIVEN an ant task with a vulnerability
|
||||
final String antTaskName = "suppression";
|
||||
|
||||
// WHEN executing the ant task
|
||||
buildFileRule.executeTarget(antTaskName);
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println(buildFileRule.getError());
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println(buildFileRule.getFullLog());
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
System.out.println("----------------------------------------------------------");
|
||||
|
||||
// THEN the ant task executed without error
|
||||
final File report = new File("target/suppression-report.html");
|
||||
assertTrue("Expected the DependencyCheck report to be generated", report.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the DependencyCheckTask deprecated suppression property throws an
|
||||
* exception with a warning.
|
||||
*/
|
||||
@Test
|
||||
public void testSuppressingSingle() {
|
||||
// GIVEN an ant task with a vulnerability using the legacy property
|
||||
final String antTaskName = "suppression-single";
|
||||
|
||||
// WHEN executing the ant task
|
||||
buildFileRule.executeTarget(antTaskName);
|
||||
|
||||
// THEN the ant task executed without error
|
||||
final File report = new File("target/suppression-single-report.html");
|
||||
assertTrue("Expected the DependencyCheck report to be generated", report.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the DependencyCheckTask deprecated suppression property throws an
|
||||
* exception with a warning.
|
||||
*/
|
||||
@Test
|
||||
public void testSuppressingMultiple() {
|
||||
// GIVEN an ant task with a vulnerability using multiple was to configure the suppression file
|
||||
final String antTaskName = "suppression-multiple";
|
||||
|
||||
// WHEN executing the ant task
|
||||
buildFileRule.executeTarget(antTaskName);
|
||||
|
||||
// THEN the ant task executed without error
|
||||
final File report = new File("target/suppression-multiple-report.html");
|
||||
assertTrue("Expected the DependencyCheck report to be generated", report.exists());
|
||||
}
|
||||
}
|
||||
@@ -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,57 @@
|
||||
|
||||
<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>
|
||||
|
||||
<target name="suppression">
|
||||
<dependency-check
|
||||
applicationName="test suppression"
|
||||
reportOutputDirectory="${project.build.directory}/suppression-report.html"
|
||||
autoupdate="false"
|
||||
failBuildOnCVSS="3">
|
||||
<suppressionfile path="${project.build.directory}/test-classes/test-suppression1.xml" />
|
||||
<suppressionfile path="${project.build.directory}/test-classes/test-suppression2.xml" />
|
||||
<fileset dir="${project.build.directory}/test-classes/jars">
|
||||
<include name="axis-1.4.jar"/>
|
||||
</fileset>
|
||||
<filelist
|
||||
dir="${project.build.directory}/test-classes/list"
|
||||
files="jetty-6.1.0.jar,org.mortbay.jetty.jar"/>
|
||||
</dependency-check>
|
||||
</target>
|
||||
<target name="suppression-single">
|
||||
<dependency-check
|
||||
applicationName="test suppression"
|
||||
reportOutputDirectory="${project.build.directory}/suppression-single-report.html"
|
||||
autoupdate="false"
|
||||
failBuildOnCVSS="3"
|
||||
suppressionFile="${project.build.directory}/test-classes/test-suppression.xml">
|
||||
<fileset dir="${project.build.directory}/test-classes/jars">
|
||||
<include name="axis-1.4.jar"/>
|
||||
</fileset>
|
||||
</dependency-check>
|
||||
</target>
|
||||
<target name="suppression-multiple">
|
||||
<dependency-check
|
||||
applicationName="test suppression"
|
||||
reportOutputDirectory="${project.build.directory}/suppression-multiple-report.html"
|
||||
autoupdate="false"
|
||||
failBuildOnCVSS="3"
|
||||
suppressionFile="${project.build.directory}/test-classes/test-suppression1.xml">
|
||||
<suppressionfile path="${project.build.directory}/test-classes/test-suppression2.xml"/>
|
||||
<fileset dir="${project.build.directory}/test-classes/jars">
|
||||
<include name="axis-1.4.jar"/>
|
||||
</fileset>
|
||||
</dependency-check>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
48
ant/src/test/resources/test-suppression.xml
Normal file
48
ant/src/test/resources/test-suppression.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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 The OWASP Foundation. All Rights Reserved.
|
||||
-->
|
||||
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: axis-1.4.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^org\.apache\.axis:axis:.*$</gav>
|
||||
<cpe>cpe:/a:apache:axis</cpe>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: org.mortbay.jetty.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^jetty:org\.mortbay\.jetty:.*$</gav>
|
||||
<cpe>cpe:/a:jetty:jetty</cpe>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: org.mortbay.jetty.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^jetty:org\.mortbay\.jetty:.*$</gav>
|
||||
<cpe>cpe:/a:mortbay:jetty</cpe>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: org.mortbay.jetty.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^jetty:org\.mortbay\.jetty:.*$</gav>
|
||||
<cpe>cpe:/a:mortbay_jetty:jetty</cpe>
|
||||
</suppress>
|
||||
</suppressions>
|
||||
27
ant/src/test/resources/test-suppression1.xml
Normal file
27
ant/src/test/resources/test-suppression1.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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 The OWASP Foundation. All Rights Reserved.
|
||||
-->
|
||||
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: axis-1.4.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^org\.apache\.axis:axis:.*$</gav>
|
||||
<cpe>cpe:/a:apache:axis</cpe>
|
||||
</suppress>
|
||||
</suppressions>
|
||||
41
ant/src/test/resources/test-suppression2.xml
Normal file
41
ant/src/test/resources/test-suppression2.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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 The OWASP Foundation. All Rights Reserved.
|
||||
-->
|
||||
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: org.mortbay.jetty.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^jetty:org\.mortbay\.jetty:.*$</gav>
|
||||
<cpe>cpe:/a:jetty:jetty</cpe>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: org.mortbay.jetty.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^jetty:org\.mortbay\.jetty:.*$</gav>
|
||||
<cpe>cpe:/a:mortbay:jetty</cpe>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: org.mortbay.jetty.jar
|
||||
]]></notes>
|
||||
<gav regex="true">^jetty:org\.mortbay\.jetty:.*$</gav>
|
||||
<cpe>cpe:/a:mortbay_jetty:jetty</cpe>
|
||||
</suppress>
|
||||
</suppressions>
|
||||
57
archetype/pom.xml
Normal file
57
archetype/pom.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<!--
|
||||
This file is part of dependency-check-maven.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Copyright (c) 2017 Jeremy Long. All Rights Reserved.
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>3.1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-plugin</artifactId>
|
||||
<name>Dependency-Check Plugin Archetype</name>
|
||||
<packaging>jar</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<configuration>
|
||||
<escapeString>\</escapeString>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>archetype-resources/pom.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>archetype-resources/pom.xml</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archetype-descriptor name="dependency-check-plugin"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<requiredProperties>
|
||||
<requiredProperty key="analyzerName">
|
||||
<defaultValue>CustomAnalyzer</defaultValue>
|
||||
</requiredProperty>
|
||||
</requiredProperties>
|
||||
<fileSets>
|
||||
<fileSet filtered="true" packaged="true" encoding="UTF-8">
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.java</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet filtered="true" encoding="UTF-8">
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet filtered="true" packaged="true" encoding="UTF-8">
|
||||
<directory>src/test/java</directory>
|
||||
<includes>
|
||||
<include>**/*.java</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet filtered="true" encoding="UTF-8">
|
||||
<directory>src/test/resources</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</archetype-descriptor>
|
||||
44
archetype/src/main/resources/archetype-resources/pom.xml
Normal file
44
archetype/src/main/resources/archetype-resources/pom.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>\${groupId}</groupId>
|
||||
<artifactId>\${artifactId}</artifactId>
|
||||
<version>\${version}</version>
|
||||
|
||||
<name>\${artifactId}</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package ${package};
|
||||
|
||||
import java.io.File;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
|
||||
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.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* An OWASP dependency-check plug-in example. If you are not implementing a
|
||||
* FileTypeAnalyzer, simple remove the annotation and the accept() method.
|
||||
*/
|
||||
public class ${analyzerName} implements Analyzer, FileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger for use throughout the ${analyzerName}.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(${analyzerName}.class);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Method implementation for the FileTypeAnalyzer; if not implementing a
|
||||
* file type analyzer this method can be removed.</p>
|
||||
* <p>
|
||||
* Determines if the analyzer can process the given file.</p>
|
||||
*
|
||||
* @param pathname the path to the file
|
||||
* @return <code>true</code> if the analyzer can process the file; otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
if (enabled) {
|
||||
//TODO implement analyze
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the analyzer.
|
||||
*
|
||||
* @return the name of the analyzer.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "${analyzerName}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 AnalysisPhase.INFORMATION_COLLECTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* The initialize method is called just after instantiation of the object.
|
||||
*
|
||||
* @param settings a reference to the configured settings
|
||||
*/
|
||||
@Override
|
||||
public void initialize(Settings settings) {
|
||||
//TODO implement initialize
|
||||
}
|
||||
|
||||
/**
|
||||
* The prepare method is called once just prior to repeated calls to
|
||||
* analyze.
|
||||
*
|
||||
* @param engine a reference to the engine
|
||||
* @throws InitializationException thrown when the analyzer cannot be
|
||||
* initialized
|
||||
*/
|
||||
@Override
|
||||
public void prepare(Engine engine) throws InitializationException {
|
||||
//TODO implement prepare
|
||||
}
|
||||
|
||||
/**
|
||||
* The close method is called after all of the dependencies have been
|
||||
* analyzed.
|
||||
*
|
||||
* @throws Exception is thrown if an exception occurs closing the analyzer.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether multiple instances of the same type of analyzer can run
|
||||
* in parallel. If the analyzer does not support parallel processing it is
|
||||
* generally best to also mark the analyze(Dependency,Engine) as synchronized.
|
||||
*
|
||||
* @return {@code true} if the analyzer supports parallel processing,
|
||||
* {@code false} else
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParallelProcessing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag indicating whether or not the analyzer is enabled.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Returns whether or not the analyzer is enabled.
|
||||
*
|
||||
* @return whether or not the analyzer is enabled
|
||||
*/
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
${package}.${analyzerName}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package ${package};
|
||||
|
||||
import java.io.File;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Test cases for ${analyzerName}
|
||||
*/
|
||||
public class ${analyzerName}Test {
|
||||
|
||||
Settings settings = null;
|
||||
|
||||
public ${analyzerName}Test() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
settings = new Settings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
settings.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of accept method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testAccept() {
|
||||
File pathname = new File("test.file");
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
boolean expResult = true;
|
||||
boolean result = instance.accept(pathname);
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of analyze method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyze() throws Exception {
|
||||
//The engine is generally null for most analyzer test cases but can be instantiated if needed.
|
||||
Engine engine = null;
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
instance.initialize(settings);
|
||||
instance.prepare(engine);
|
||||
|
||||
File file = new File(${analyzerName}.class.getClassLoader().getResource("test.file").toURI().getPath());
|
||||
Dependency dependency = new Dependency(file);
|
||||
|
||||
//TODO uncomment the following line and add assertions against the dependency.
|
||||
//instance.analyze(dependency, engine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getName method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetName() {
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
String expResult = "${analyzerName}";
|
||||
String result = instance.getName();
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getAnalysisPhase method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetAnalysisPhase() {
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
AnalysisPhase expResult = AnalysisPhase.INFORMATION_COLLECTION;
|
||||
AnalysisPhase result = instance.getAnalysisPhase();
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of initialize method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testInitialize() throws Exception {
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
instance.initialize(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of close method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testClose() throws Exception {
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
instance.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of supportsParallelProcessing method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testSupportsParallelProcessing() {
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
boolean expResult = true;
|
||||
boolean result = instance.supportsParallelProcessing();
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of isEnabled method, of class ${analyzerName}.
|
||||
*/
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
${analyzerName} instance = new ${analyzerName}();
|
||||
boolean expResult = true;
|
||||
boolean result = instance.isEnabled();
|
||||
assertEquals(expResult, result);
|
||||
}
|
||||
}
|
||||
10
archetype/src/site/markdown/index.md.vm
Normal file
10
archetype/src/site/markdown/index.md.vm
Normal file
@@ -0,0 +1,10 @@
|
||||
About
|
||||
=====
|
||||
OWASP dependency-check-plugin is a maven archetype for generating a maven project for
|
||||
a dependency-check plugin (i.e. a project containing one or more analyzers).
|
||||
|
||||
Usage
|
||||
=====
|
||||
```bash
|
||||
mvn archetype:generate -DarchetypeGroupId=org.owasp -DarchetypeArtifactId=dependency-check-plugin -DarchetypeVersion=${project.version}
|
||||
```
|
||||
1
archetype/src/site/resources/images/dc.svg
Normal file
1
archetype/src/site/resources/images/dc.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.0 KiB |
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!--
|
||||
This file is part of dependency-check-jenkins.
|
||||
This file is part of dependency-check-plugin.
|
||||
|
||||
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,21 @@ 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
Copyright (c) 2017 Jeremy Long. All Rights Reserved.
|
||||
-->
|
||||
<project name="dependency-check-jenkins">
|
||||
<bannerLeft>
|
||||
<name>OWASP dependency-check-jenkins</name>
|
||||
<alt>OWASP dependency-check-maven</alt>
|
||||
<src>./images/dc-jenkins.svg</src>
|
||||
<project name="dependency-check-plugin">
|
||||
<bannerLeft>
|
||||
<name>OWASP dependency-check-plugin</name>
|
||||
<alt>OWASP dependency-check-plugin</alt>
|
||||
<src>/images/dc.svg</src>
|
||||
</bannerLeft>
|
||||
<body>
|
||||
<breadcrumbs>
|
||||
<item name="dependency-check" href="../index.html"/>
|
||||
</breadcrumbs>
|
||||
<menu ref="reports" />
|
||||
<menu name="Getting Started">
|
||||
<item name="Usage" href="index.html"/>
|
||||
</menu>
|
||||
<menu ref="reports"/>
|
||||
</body>
|
||||
</project>
|
||||
114
build-reporting/pom.xml
Normal file
114
build-reporting/pom.xml
Normal file
@@ -0,0 +1,114 @@
|
||||
<!--
|
||||
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>3.1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<name>Dependency-Check Build-Reporting</name>
|
||||
<artifactId>build-reporting</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<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.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>report-merge</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>merge</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fileSets>
|
||||
<fileSet implementation="org.apache.maven.shared.model.fileset.FileSet">
|
||||
<directory>${project.basedir}/../</directory>
|
||||
<includes>
|
||||
<include>utils/target/coverage-reports/*.exec</include>
|
||||
<include>core/target/coverage-reports/*.exec</include>
|
||||
<include>cli/target/coverage-reports/*.exec</include>
|
||||
<include>ant/target/coverage-reports/*.exec</include>
|
||||
<include>maven/target/coverage-reports/*.exec</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report-aggregate</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>report-aggregate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target/coverage-reports/</outputDirectory>
|
||||
<dataFileIncludes>
|
||||
<dataFileInclude>target/coverage-reports/jacoco-ut.exec</dataFileInclude>
|
||||
<dataFileInclude>target/coverage-reports/jacoco-it.exec</dataFileInclude>
|
||||
</dataFileIncludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
5
build-reporting/src/site/markdown/index.md
Normal file
5
build-reporting/src/site/markdown/index.md
Normal 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.
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
151
cli/pom.xml
Normal file
151
cli/pom.xml
Normal file
@@ -0,0 +1,151 @@
|
||||
<!--
|
||||
This file is part of Dependency-Check.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Copyright (c) 2012 - 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>3.1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-cli</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Dependency-Check Command Line</name>
|
||||
<description>dependency-check-cli is an command line tool that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the scanned project dependencies. The tool will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
|
||||
<build>
|
||||
<finalName>dependency-check-${project.version}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**/*.properties</include>
|
||||
<include>logback.xml</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}</directory>
|
||||
<targetPath>META-INF</targetPath>
|
||||
<includes>
|
||||
<include>LICENSE.txt</include>
|
||||
<include>NOTICE.txt</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.owasp.dependencycheck.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>appassembler-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<programs>
|
||||
<program>
|
||||
<mainClass>org.owasp.dependencycheck.App</mainClass>
|
||||
<id>dependency-check</id>
|
||||
</program>
|
||||
</programs>
|
||||
<assembleDirectory>${project.build.directory}/release</assembleDirectory>
|
||||
<licenseHeaderFile>${basedir}/src/main/assembly/license.txt</licenseHeaderFile>
|
||||
<binFileExtensions>
|
||||
<unix>.sh</unix>
|
||||
</binFileExtensions>
|
||||
<configurationDirectory>plugins/*</configurationDirectory>
|
||||
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>assemble</id>
|
||||
<goals>
|
||||
<goal>assemble</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<attach>false</attach> <!-- don't install/deploy this archive -->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>create-distribution</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/release.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-utils</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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>
|
||||
@@ -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>
|
||||
593
cli/src/main/java/org/owasp/dependencycheck/App.java
Normal file
593
cli/src/main/java/org/owasp/dependencycheck/App.java
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* This file is part of dependency-check-cli.
|
||||
*
|
||||
* 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;
|
||||
|
||||
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;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The command line interface for the DependencyCheck application.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private Settings settings = null;
|
||||
|
||||
/**
|
||||
* The main method for the application.
|
||||
*
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
int exitCode = 0;
|
||||
final App app = new App();
|
||||
exitCode = app.run(args);
|
||||
LOGGER.debug("Exit code: {}", exitCode);
|
||||
System.exit(exitCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the App object.
|
||||
*/
|
||||
public App() {
|
||||
settings = new Settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the App object; this method is used for testing.
|
||||
*
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
protected App(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main CLI entry-point into the application.
|
||||
*
|
||||
* @param args the command line arguments
|
||||
* @return the exit code to return
|
||||
*/
|
||||
public int run(String[] args) {
|
||||
int exitCode = 0;
|
||||
final CliParser cli = new CliParser(settings);
|
||||
|
||||
try {
|
||||
cli.parse(args);
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
cli.printHelp();
|
||||
return -1;
|
||||
} catch (ParseException ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
cli.printHelp();
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (cli.getVerboseLog() != null) {
|
||||
prepareLogger(cli.getVerboseLog());
|
||||
}
|
||||
|
||||
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;
|
||||
return exitCode;
|
||||
}
|
||||
File db;
|
||||
try {
|
||||
db = new File(settings.getDataDirectory(), settings.getString(Settings.KEYS.DB_FILE_NAME, "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 exist: {}", db.getAbsolutePath());
|
||||
exitCode = -6;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Unable to delete the database");
|
||||
exitCode = -7;
|
||||
} finally {
|
||||
settings.cleanup();
|
||||
}
|
||||
}
|
||||
} else if (cli.isGetVersion()) {
|
||||
cli.printVersionInfo();
|
||||
} else if (cli.isUpdateOnly()) {
|
||||
try {
|
||||
populateSettings(cli);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.debug("Error loading properties file", ex);
|
||||
exitCode = -4;
|
||||
return exitCode;
|
||||
}
|
||||
try {
|
||||
runUpdateOnly();
|
||||
} catch (UpdateException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
exitCode = -8;
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
exitCode = -9;
|
||||
} finally {
|
||||
settings.cleanup();
|
||||
}
|
||||
} else if (cli.isRunScan()) {
|
||||
try {
|
||||
populateSettings(cli);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.debug("Error loading properties file", ex);
|
||||
exitCode = -4;
|
||||
return exitCode;
|
||||
}
|
||||
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()) {
|
||||
if (e.getMessage() != null) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
settings.cleanup();
|
||||
}
|
||||
} else {
|
||||
cli.printHelp();
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 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 int runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
|
||||
String[] excludes, int symLinkDepth, int cvssFailScore) throws InvalidScanPathException, DatabaseException,
|
||||
ExceptionCollection, ReportException {
|
||||
Engine engine = null;
|
||||
try {
|
||||
final List<String> antStylePaths = getPaths(files);
|
||||
final Set<File> paths = scanAntStylePaths(antStylePaths, symLinkDepth, excludes);
|
||||
|
||||
engine = new Engine(settings);
|
||||
engine.scan(paths);
|
||||
|
||||
ExceptionCollection exCol = null;
|
||||
try {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (exCol != null && !exCol.getExceptions().isEmpty()) {
|
||||
throw exCol;
|
||||
}
|
||||
return determineReturnCode(engine, cvssFailScore);
|
||||
} finally {
|
||||
if (engine != null) {
|
||||
engine.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the return code based on if one of the dependencies scanned
|
||||
* has a vulnerability with a CVSS score above the cvssFailScore.
|
||||
*
|
||||
* @param engine the engine used during analysis
|
||||
* @param cvssFailScore the max allowed CVSS score
|
||||
* @return returns <code>1</code> if a severe enough vulnerability is
|
||||
* identified; otherwise <code>0</code>
|
||||
*/
|
||||
private int determineReturnCode(Engine engine, int cvssFailScore) {
|
||||
int retCode = 0;
|
||||
//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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the give Ant Style paths and collects the actual files.
|
||||
*
|
||||
* @param antStylePaths a list of ant style paths to scan for actual files
|
||||
* @param symLinkDepth the depth to traverse symbolic links
|
||||
* @param excludes an array of ant style excludes
|
||||
* @return returns the set of identified files
|
||||
* @throws InvalidScanPathException thrown when the scan path is invalid
|
||||
*/
|
||||
private Set<File> scanAntStylePaths(List<String> antStylePaths, int symLinkDepth, String[] excludes)
|
||||
throws InvalidScanPathException {
|
||||
final Set<File> paths = new HashSet<>();
|
||||
for (String file : antStylePaths) {
|
||||
LOGGER.debug("Scanning {}", file);
|
||||
final DirectoryScanner scanner = new DirectoryScanner();
|
||||
String include = file.replace('\\', '/');
|
||||
File baseDir;
|
||||
|
||||
if (include.startsWith("//")) {
|
||||
throw new InvalidScanPathException("Unable to scan paths specified by //");
|
||||
} else {
|
||||
final int pos = getLastFileSeparator(include);
|
||||
final String tmpBase = include.substring(0, pos);
|
||||
final String tmpInclude = include.substring(pos + 1);
|
||||
if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0
|
||||
|| (new File(include)).isFile()) {
|
||||
baseDir = new File(tmpBase);
|
||||
include = tmpInclude;
|
||||
} else {
|
||||
baseDir = new File(tmpBase, tmpInclude);
|
||||
include = "**/*";
|
||||
}
|
||||
}
|
||||
scanner.setBasedir(baseDir);
|
||||
final String[] includes = {include};
|
||||
scanner.setIncludes(includes);
|
||||
scanner.setMaxLevelsOfSymlinks(symLinkDepth);
|
||||
if (symLinkDepth <= 0) {
|
||||
scanner.setFollowSymlinks(false);
|
||||
}
|
||||
if (excludes != null && excludes.length > 0) {
|
||||
scanner.addExcludes(excludes);
|
||||
}
|
||||
scanner.scan();
|
||||
if (scanner.getIncludedFilesCount() > 0) {
|
||||
for (String s : scanner.getIncludedFiles()) {
|
||||
final File f = new File(baseDir, s);
|
||||
LOGGER.debug("Found file {}", f.toString());
|
||||
paths.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the ant style paths from the given array of files.
|
||||
*
|
||||
* @param files an array of file paths
|
||||
* @return a list containing ant style paths
|
||||
*/
|
||||
private List<String> getPaths(String[] files) {
|
||||
final List<String> antStylePaths = new ArrayList<>();
|
||||
for (String file : files) {
|
||||
final String antPath = ensureCanonicalPath(file);
|
||||
antStylePaths.add(antPath);
|
||||
}
|
||||
return antStylePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() throws UpdateException, DatabaseException {
|
||||
try (Engine engine = new Engine(settings)) {
|
||||
engine.doUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @throws InvalidSettingException thrown when a user defined properties
|
||||
* file is unable to be loaded.
|
||||
*/
|
||||
protected void populateSettings(CliParser cli) throws InvalidSettingException {
|
||||
final String connectionTimeout = cli.getConnectionTimeout();
|
||||
final String proxyServer = cli.getProxyServer();
|
||||
final String proxyPort = cli.getProxyPort();
|
||||
final String proxyUser = cli.getProxyUsername();
|
||||
final String proxyPass = cli.getProxyPassword();
|
||||
final String dataDirectory = cli.getDataDirectory();
|
||||
final File propertiesFile = cli.getPropertiesFile();
|
||||
final String[] suppressionFiles = cli.getSuppressionFiles();
|
||||
final String hintsFile = cli.getHintsFile();
|
||||
final String nexusUrl = cli.getNexusUrl();
|
||||
final String databaseDriverName = cli.getDatabaseDriverName();
|
||||
final String databaseDriverPath = cli.getDatabaseDriverPath();
|
||||
final String connectionString = cli.getConnectionString();
|
||||
final String databaseUser = cli.getDatabaseUser();
|
||||
final String databasePassword = cli.getDatabasePassword();
|
||||
final String additionalZipExtensions = cli.getAdditionalZipExtensions();
|
||||
final String pathToMono = cli.getPathToMono();
|
||||
final String cveMod12 = cli.getModifiedCve12Url();
|
||||
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();
|
||||
final Boolean retiredEnabled = cli.isRetiredEnabled();
|
||||
|
||||
if (propertiesFile != null) {
|
||||
try {
|
||||
settings.mergeProperties(propertiesFile);
|
||||
} catch (FileNotFoundException ex) {
|
||||
throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
|
||||
} catch (IOException 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. 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);
|
||||
} else if (System.getProperty("basedir") != null) {
|
||||
final File dataDir = new File(System.getProperty("basedir"), "data");
|
||||
settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
|
||||
} else {
|
||||
final File jarPath = new File(App.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());
|
||||
}
|
||||
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.HINTS_FILE, hintsFile);
|
||||
settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
|
||||
|
||||
settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFiles);
|
||||
|
||||
//File Type Analyzer Settings
|
||||
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
|
||||
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIRED_ENABLED, retiredEnabled);
|
||||
|
||||
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_NSP_PACKAGE_ENABLED, !cli.isNspDisabled());
|
||||
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);
|
||||
settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12);
|
||||
settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file appender and adds it to logback.
|
||||
*
|
||||
* @param verboseLog the path to the verbose log file
|
||||
*/
|
||||
private void prepareLogger(String verboseLog) {
|
||||
final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton();
|
||||
final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory();
|
||||
|
||||
final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||
encoder.setPattern("%d %C:%L%n%-5level - %msg%n");
|
||||
encoder.setContext(context);
|
||||
encoder.start();
|
||||
final FileAppender<ILoggingEvent> fa = new FileAppender<>();
|
||||
fa.setAppend(true);
|
||||
fa.setEncoder(encoder);
|
||||
fa.setContext(context);
|
||||
fa.setFile(verboseLog);
|
||||
final File f = new File(verboseLog);
|
||||
String name = f.getName();
|
||||
final int i = name.lastIndexOf('.');
|
||||
if (i > 1) {
|
||||
name = name.substring(0, i);
|
||||
}
|
||||
fa.setName(name);
|
||||
fa.start();
|
||||
final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
|
||||
rootLogger.addAppender(fa);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ?).
|
||||
*
|
||||
* @param path the path to canonicalize
|
||||
* @return the canonical path
|
||||
*/
|
||||
protected String ensureCanonicalPath(String path) {
|
||||
String basePath;
|
||||
String wildCards = null;
|
||||
final String file = path.replace('\\', '/');
|
||||
if (file.contains("*") || file.contains("?")) {
|
||||
|
||||
int pos = getLastFileSeparator(file);
|
||||
if (pos < 0) {
|
||||
return file;
|
||||
}
|
||||
pos += 1;
|
||||
basePath = file.substring(0, pos);
|
||||
wildCards = file.substring(pos);
|
||||
} else {
|
||||
basePath = file;
|
||||
}
|
||||
|
||||
File f = new File(basePath);
|
||||
try {
|
||||
f = f.getCanonicalFile();
|
||||
if (wildCards != null) {
|
||||
f = new File(f, wildCards);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.warn("Invalid path '{}' was provided.", path);
|
||||
LOGGER.debug("Invalid path provided", ex);
|
||||
}
|
||||
return f.getAbsolutePath().replace('\\', '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the last file separator.
|
||||
*
|
||||
* @param file a file path
|
||||
* @return the position of the last file separator
|
||||
*/
|
||||
private int getLastFileSeparator(String file) {
|
||||
if (file.contains("*") || file.contains("?")) {
|
||||
int p1 = file.indexOf('*');
|
||||
int p2 = file.indexOf('?');
|
||||
p1 = p1 > 0 ? p1 : file.length();
|
||||
p2 = p2 > 0 ? p2 : file.length();
|
||||
int pos = p1 < p2 ? p1 : p2;
|
||||
pos = file.lastIndexOf('/', pos);
|
||||
return pos;
|
||||
} else {
|
||||
return file.lastIndexOf('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
69
cli/src/site/markdown/arguments.md
Normal file
69
cli/src/site/markdown/arguments.md
Normal file
@@ -0,0 +1,69 @@
|
||||
Command Line Arguments
|
||||
======================
|
||||
|
||||
The following table lists the command line arguments:
|
||||
|
||||
Short | Argument Name | Parameter | Description | Requirement
|
||||
-------|------------------------|-----------------|-------------|------------
|
||||
| \-\-project | \<name\> | The name of the project being scanned. | Required
|
||||
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. directory/**/*.jar). | Required
|
||||
| \-\-exclude | \<pattern\> | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**). | Optional
|
||||
| \-\-symLink | \<depth\> | The depth that symbolic links will be followed; the default is 0 meaning symbolic links will not be followed. | Optional
|
||||
\-o | \-\-out | \<path\> | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional
|
||||
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, 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 | \<files\> | The file paths to the suppression XML files; used to suppress [false positives](../general/suppression.html). This can be specified more than once to utilize multiple suppression files. | 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
|
||||
| \-\-enableRetired | | Enable the [retired analyzers](../analyzers/index.html). If not set the analyzers marked as retired below will not be loaded or used. | Optional
|
||||
|
||||
Advanced Options
|
||||
================
|
||||
Short | Argument Name | Parameter | Description | Default Value
|
||||
-------|------------------------|-----------------|----------------------------------------------------------------------------------|-------------------
|
||||
| \-\-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. |
|
||||
| \-\-updateonly | | If set only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. |
|
||||
| \-\-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 [retired](../analyzers/index.html) Node.js Package Analyzer will be used. | false
|
||||
| \-\-disableNSP | | Sets whether the NSP 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. |
|
||||
| \-\-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 (requires Nexus Pro). 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. |
|
||||
| \-\-nexusUsesProxy | \<true\|false\> | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||
| \-\-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. |
|
||||
| \-\-bundleAudit | | The path to the bundle-audit executable. |
|
||||
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources; see the [proxy configuration](../data/proxy.html) page for more information. |
|
||||
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. |
|
||||
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. |
|
||||
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. |
|
||||
| \-\-proxyuser | \<user\> | The proxy username to use when downloading resources. |
|
||||
| \-\-connectionString | \<connStr\> | The connection string to the database. |
|
||||
| \-\-dbDriverName | \<driver\> | The database driver name. |
|
||||
| \-\-dbDriverPath | \<path\> | The path to the database driver; note, this does not need to be set unless the JAR is outside of the class path. |
|
||||
| \-\-dbPassword | \<password\> | The password for connecting to the database. |
|
||||
| \-\-dbUser | \<user\> | The username used to connect to the database. |
|
||||
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. |
|
||||
| \-\-purge | | Delete the local copy of the NVD. This is used to force a refresh of the data. |
|
||||
@@ -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
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
194
cli/src/test/java/org/owasp/dependencycheck/AppTest.java
Normal file
194
cli/src/test/java/org/owasp/dependencycheck/AppTest.java
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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 The OWASP Foundation. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
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.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.owasp.dependencycheck.utils.Settings.KEYS;
|
||||
|
||||
/**
|
||||
* Tests for the {@link AppTest} class.
|
||||
*/
|
||||
public class AppTest extends BaseTest {
|
||||
|
||||
/**
|
||||
* Test rule for asserting exceptions and their contents.
|
||||
*/
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
/**
|
||||
* Test of ensureCanonicalPath method, of class App.
|
||||
*/
|
||||
@Test
|
||||
public void testEnsureCanonicalPath() {
|
||||
String file = "../*.jar";
|
||||
App instance = new App(getSettings());
|
||||
String result = instance.ensureCanonicalPath(file);
|
||||
assertFalse(result.contains(".."));
|
||||
assertTrue(result.endsWith("*.jar"));
|
||||
|
||||
file = "../some/skip/../path/file.txt";
|
||||
String expResult = "/some/path/file.txt";
|
||||
result = instance.ensureCanonicalPath(file);
|
||||
assertTrue("result=" + result, result.endsWith(expResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that boolean properties can be set on the CLI and parsed into the
|
||||
* {@link Settings}.
|
||||
*
|
||||
* @throws Exception the unexpected {@link Exception}.
|
||||
*/
|
||||
@Test
|
||||
public void testPopulateSettings() throws Exception {
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an {@link UnrecognizedOptionException} is thrown when a
|
||||
* property that is not supported is specified on the CLI.
|
||||
*
|
||||
* @throws Exception the unexpected {@link Exception}.
|
||||
*/
|
||||
@Test
|
||||
public void testPopulateSettingsException() throws Exception {
|
||||
String[] args = {"-invalidPROPERTY"};
|
||||
|
||||
expectedException.expect(UnrecognizedOptionException.class);
|
||||
expectedException.expectMessage("Unrecognized option: -invalidPROPERTY");
|
||||
testBooleanProperties(args, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a single suppression file can be set using the CLI.
|
||||
*
|
||||
* @throws Exception the unexpected {@link Exception}.
|
||||
*/
|
||||
@Test
|
||||
public void testPopulatingSuppressionSettingsWithASingleFile() throws Exception {
|
||||
// GIVEN CLI properties with the mandatory arguments
|
||||
File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
|
||||
|
||||
// AND a single suppression file
|
||||
String[] args = {"-P", prop.getAbsolutePath(), "--suppression", "another-file.xml"};
|
||||
|
||||
// WHEN parsing the CLI arguments
|
||||
final CliParser cli = new CliParser(getSettings());
|
||||
cli.parse(args);
|
||||
final App classUnderTest = new App(getSettings());
|
||||
classUnderTest.populateSettings(cli);
|
||||
|
||||
// THEN the suppression file is set in the settings for use in the application core
|
||||
assertThat("Expected the suppression file to be set in the Settings", getSettings().getString(KEYS.SUPPRESSION_FILE), is("another-file.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that multiple suppression files can be set using the CLI.
|
||||
*
|
||||
* @throws Exception the unexpected {@link Exception}.
|
||||
*/
|
||||
@Test
|
||||
public void testPopulatingSuppressionSettingsWithMultipleFiles() throws Exception {
|
||||
// GIVEN CLI properties with the mandatory arguments
|
||||
File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
|
||||
|
||||
// AND a single suppression file
|
||||
String[] args = {"-P", prop.getAbsolutePath(), "--suppression", "first-file.xml", "another-file.xml"};
|
||||
|
||||
// WHEN parsing the CLI arguments
|
||||
final CliParser cli = new CliParser(getSettings());
|
||||
cli.parse(args);
|
||||
final App classUnderTest = new App(getSettings());
|
||||
classUnderTest.populateSettings(cli);
|
||||
|
||||
// THEN the suppression file is set in the settings for use in the application core
|
||||
assertThat("Expected the suppression files to be set in the Settings with a separator", getSettings().getString(KEYS.SUPPRESSION_FILE), is("first-file.xml,another-file.xml"));
|
||||
}
|
||||
|
||||
private boolean testBooleanProperties(String[] args, Map<String, Boolean> expected) throws URISyntaxException, FileNotFoundException, ParseException, InvalidSettingException {
|
||||
this.reloadSettings();
|
||||
final CliParser cli = new CliParser(getSettings());
|
||||
cli.parse(args);
|
||||
App instance = new App(getSettings());
|
||||
instance.populateSettings(cli);
|
||||
boolean results = true;
|
||||
for (Map.Entry<String, Boolean> entry : expected.entrySet()) {
|
||||
results &= getSettings().getBoolean(entry.getKey()) == entry.getValue();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
62
cli/src/test/java/org/owasp/dependencycheck/BaseTest.java
Normal file
62
cli/src/test/java/org/owasp/dependencycheck/BaseTest.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2014 OWASP.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.owasp.dependencycheck;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class BaseTest {
|
||||
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private Settings settings;
|
||||
|
||||
/**
|
||||
* Initialize the {@link Settings}.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
settings = new Settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the {@link Settings}.
|
||||
*/
|
||||
@After
|
||||
public void tearDown() {
|
||||
settings.cleanup(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings for the test cases.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
protected void reloadSettings() {
|
||||
tearDown();
|
||||
setUp();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -36,25 +33,7 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class CliParserTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
Settings.initialize();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
Settings.cleanup(true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
public class CliParserTest extends BaseTest {
|
||||
|
||||
/**
|
||||
* Test of parse method, of class CliParser.
|
||||
@@ -70,7 +49,7 @@ public class CliParserTest {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
System.setOut(new PrintStream(baos));
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
instance.parse(args);
|
||||
|
||||
Assert.assertFalse(instance.isGetVersion());
|
||||
@@ -89,7 +68,7 @@ public class CliParserTest {
|
||||
String[] args = {"-help"};
|
||||
PrintStream out = System.out;
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
instance.parse(args);
|
||||
|
||||
Assert.assertFalse(instance.isGetVersion());
|
||||
@@ -107,7 +86,7 @@ public class CliParserTest {
|
||||
|
||||
String[] args = {"-version"};
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
instance.parse(args);
|
||||
Assert.assertTrue(instance.isGetVersion());
|
||||
Assert.assertFalse(instance.isGetHelp());
|
||||
@@ -115,6 +94,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(getSettings());
|
||||
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(getSettings());
|
||||
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(getSettings());
|
||||
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.
|
||||
*
|
||||
@@ -132,7 +168,7 @@ public class CliParserTest {
|
||||
System.setOut(new PrintStream(baos_out));
|
||||
System.setErr(new PrintStream(baos_err));
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
|
||||
try {
|
||||
instance.parse(args);
|
||||
@@ -154,7 +190,7 @@ public class CliParserTest {
|
||||
|
||||
String[] args = {"-scan"};
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
|
||||
try {
|
||||
instance.parse(args);
|
||||
@@ -177,7 +213,7 @@ public class CliParserTest {
|
||||
|
||||
String[] args = {"-scan", "jar.that.does.not.exist", "-app", "test"};
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
try {
|
||||
instance.parse(args);
|
||||
} catch (FileNotFoundException ex) {
|
||||
@@ -196,10 +232,10 @@ 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();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
instance.parse(args);
|
||||
|
||||
Assert.assertEquals(path.getCanonicalPath(), instance.getScanFiles()[0]);
|
||||
@@ -221,7 +257,7 @@ public class CliParserTest {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
System.setOut(new PrintStream(baos));
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
instance.printVersionInfo();
|
||||
try {
|
||||
baos.flush();
|
||||
@@ -250,7 +286,7 @@ public class CliParserTest {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
System.setOut(new PrintStream(baos));
|
||||
|
||||
CliParser instance = new CliParser();
|
||||
CliParser instance = new CliParser(getSettings());
|
||||
String[] args = {"-h"};
|
||||
instance.parse(args);
|
||||
instance.printHelp();
|
||||
33
cli/src/test/resources/sample.properties
Normal file
33
cli/src/test/resources/sample.properties
Normal file
@@ -0,0 +1,33 @@
|
||||
autoupdate=false
|
||||
somethingmadeup=test
|
||||
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
|
||||
33
cli/src/test/resources/sample2.properties
Normal file
33
cli/src/test/resources/sample2.properties
Normal 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
|
||||
@@ -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
|
||||
@@ -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>3.1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-core</artifactId>
|
||||
@@ -28,15 +28,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
|
||||
<name>Dependency-Check Core</name>
|
||||
<description>dependency-check-core is the engine and reporting tool used to identify and report if there are any known, publicly disclosed vulnerabilities in the scanned project's dependencies. The engine extracts meta-data from the dependencies and uses this to do fuzzy key-word matching against the Common Platfrom Enumeration (CPE), if any CPE identifiers are found the associated Common Vulnerability and Exposure (CVE) entries are added to the generated report.</description>
|
||||
<!-- 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}/dependency-check-core</url>
|
||||
</site>
|
||||
</distributionManagement>
|
||||
<!-- end copy -->
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
@@ -83,9 +74,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>
|
||||
@@ -102,6 +90,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/test-classes</outputDirectory>
|
||||
<includeScope>test</includeScope>
|
||||
<excludeArtifactIds>dependency-check-utils</excludeArtifactIds>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
@@ -110,257 +99,32 @@ 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>
|
||||
<report>report-only</report>
|
||||
<report>failsafe-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>
|
||||
<version>${reporting.checkstyle-plugin.version}</version>
|
||||
<configuration>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
<enableFilesSummary>false</enableFilesSummary>
|
||||
<configLocation>${basedir}/../src/main/config/checkstyle-checks.xml</configLocation>
|
||||
<headerLocation>${basedir}/../src/main/config/checkstyle-header.txt</headerLocation>
|
||||
<suppressionsLocation>${basedir}/../src/main/config/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>${reporting.pmd-plugin.version}</version>
|
||||
<configuration>
|
||||
<targetJdk>1.6</targetJdk>
|
||||
<linkXref>true</linkXref>
|
||||
<sourceEncoding>utf-8</sourceEncoding>
|
||||
<excludes>
|
||||
<exclude>**/generated/*.java</exclude>
|
||||
</excludes>
|
||||
<rulesets>
|
||||
<ruleset>../src/main/config/dcrules.xml</ruleset>
|
||||
<ruleset>/rulesets/java/basic.xml</ruleset>
|
||||
<ruleset>/rulesets/java/imports.xml</ruleset>
|
||||
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
|
||||
</rulesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>${reporting.findbugs-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.vdurmont</groupId>
|
||||
<artifactId>semver4j</artifactId>
|
||||
</dependency>
|
||||
<!-- 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 +135,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 +164,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,17 +186,26 @@ 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>
|
||||
<!-- The following dependencies are only used during testing -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<!-- The following dependencies are only used during testing
|
||||
and must not be converted to a properties based version number -->
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.scm</groupId>
|
||||
<artifactId>maven-scm-provider-cvsexe</artifactId>
|
||||
@@ -559,6 +321,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 +347,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 +366,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 +382,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 +454,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 +524,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 +574,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profile-->
|
||||
</profiles>
|
||||
</project>
|
||||
115
core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java
Normal file
115
core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Task to support parallelism of dependency-check analysis. Analyses a single
|
||||
* {@link Dependency} by a specific {@link Analyzer}.
|
||||
*
|
||||
* @author Stefan Neuhaus
|
||||
*/
|
||||
@ThreadSafe
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions) {
|
||||
this.analyzer = analyzer;
|
||||
this.dependency = dependency;
|
||||
this.engine = engine;
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the analysis task.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
@Override
|
||||
public Void call() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
1129
core/src/main/java/org/owasp/dependencycheck/Engine.java
Normal file
1129
core/src/main/java/org/owasp/dependencycheck/Engine.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -20,13 +20,15 @@ package org.owasp.dependencycheck.agent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
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,18 +36,20 @@ 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<Dependency> dependencies = new ArrayList<Dependency>();
|
||||
* 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);
|
||||
* dependency.getVendorEvidence().addEvidence("my-datasource", "vendor", "mortbay", Confidence.HIGH);
|
||||
* dependency.addEvidence(EvidenceType.PRODUCT, "my-datasource", "name", "Jetty", Confidence.HIGH);
|
||||
* dependency.addEvidence(EvidenceType.VERSION, "my-datasource", "version", "5.1.10", Confidence.HIGH);
|
||||
* dependency.addEvidence(EvidenceType.VENDOR, "my-datasource", "vendor", "mortbay", Confidence.HIGH);
|
||||
* dependencies.add(dependency);
|
||||
*
|
||||
* DependencyCheckScanAgent scan = new DependencyCheckScanAgent();
|
||||
@@ -55,11 +59,13 @@ import org.slf4j.LoggerFactory;
|
||||
* scan.execute();
|
||||
* </pre>
|
||||
*
|
||||
* @author Steve Springett <steve.springett@owasp.org>
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@NotThreadSafe
|
||||
public class DependencyCheckScanAgent {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="private fields">
|
||||
/**
|
||||
* System specific new line character.
|
||||
*/
|
||||
@@ -72,6 +78,160 @@ 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;
|
||||
/**
|
||||
* Sets whether the data directory should be updated without performing a
|
||||
* scan. Default is false.
|
||||
*/
|
||||
private boolean updateOnly = false;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* The starting string that identifies CPEs that are qualified to be imported.
|
||||
*/
|
||||
private String cpeStartsWithFilter;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private Settings settings;
|
||||
/**
|
||||
* The path to optional dependency-check properties file. This will be used
|
||||
* to side-load additional user-defined properties.
|
||||
* {@link Settings#mergeProperties(String)}
|
||||
*/
|
||||
private String propertiesFilePath;
|
||||
//</editor-fold>
|
||||
//<editor-fold defaultstate="collapsed" desc="getters/setters">
|
||||
|
||||
/**
|
||||
* Get the value of applicationName.
|
||||
@@ -91,11 +251,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 +269,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 +287,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 +305,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 +323,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.
|
||||
*
|
||||
@@ -210,9 +342,22 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* flag indicating whether or not to generate a report of findings.
|
||||
* Get the value of updateOnly.
|
||||
*
|
||||
* @return the value of updateOnly
|
||||
*/
|
||||
private boolean generateReport = true;
|
||||
public boolean isUpdateOnly() {
|
||||
return updateOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of updateOnly.
|
||||
*
|
||||
* @param updateOnly new value of updateOnly
|
||||
*/
|
||||
public void setUpdateOnly(boolean updateOnly) {
|
||||
this.updateOnly = updateOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of generateReport.
|
||||
@@ -232,12 +377,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 +395,6 @@ public class DependencyCheckScanAgent {
|
||||
this.reportFormat = reportFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Proxy Server.
|
||||
*/
|
||||
private String proxyServer;
|
||||
|
||||
/**
|
||||
* Get the value of proxyServer.
|
||||
*
|
||||
@@ -283,7 +417,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 +438,6 @@ public class DependencyCheckScanAgent {
|
||||
this.proxyServer = proxyUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Proxy Port.
|
||||
*/
|
||||
private String proxyPort;
|
||||
|
||||
/**
|
||||
* Get the value of proxyPort.
|
||||
*
|
||||
@@ -325,11 +456,6 @@ public class DependencyCheckScanAgent {
|
||||
this.proxyPort = proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Proxy username.
|
||||
*/
|
||||
private String proxyUsername;
|
||||
|
||||
/**
|
||||
* Get the value of proxyUsername.
|
||||
*
|
||||
@@ -348,11 +474,6 @@ public class DependencyCheckScanAgent {
|
||||
this.proxyUsername = proxyUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Proxy password.
|
||||
*/
|
||||
private String proxyPassword;
|
||||
|
||||
/**
|
||||
* Get the value of proxyPassword.
|
||||
*
|
||||
@@ -371,11 +492,6 @@ public class DependencyCheckScanAgent {
|
||||
this.proxyPassword = proxyPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Connection Timeout.
|
||||
*/
|
||||
private String connectionTimeout;
|
||||
|
||||
/**
|
||||
* Get the value of connectionTimeout.
|
||||
*
|
||||
@@ -394,11 +510,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 +528,6 @@ public class DependencyCheckScanAgent {
|
||||
this.logFile = logFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* The path to the suppression file.
|
||||
*/
|
||||
private String suppressionFile;
|
||||
|
||||
/**
|
||||
* Get the value of suppressionFile.
|
||||
*
|
||||
@@ -440,11 +546,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.
|
||||
*
|
||||
@@ -464,9 +565,20 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the Maven Central analyzer is enabled.
|
||||
* Sets starting string that identifies CPEs that are qualified to be imported.
|
||||
* @param cpeStartsWithFilter filters CPEs based on this starting string (i.e. cpe:/a: )
|
||||
*/
|
||||
private boolean centralAnalyzerEnabled = true;
|
||||
public void setCpeStartsWithFilter(String cpeStartsWithFilter) {
|
||||
this.cpeStartsWithFilter = cpeStartsWithFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the starting string that identifies CPEs that are qualified to be imported.
|
||||
* @return the CPE starting filter (i.e. cpe:/a: )
|
||||
*/
|
||||
public String getCpeStartsWithFilter() {
|
||||
return cpeStartsWithFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of centralAnalyzerEnabled.
|
||||
@@ -486,11 +598,6 @@ public class DependencyCheckScanAgent {
|
||||
this.centralAnalyzerEnabled = centralAnalyzerEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of Maven Central.
|
||||
*/
|
||||
private String centralUrl;
|
||||
|
||||
/**
|
||||
* Get the value of centralUrl.
|
||||
*
|
||||
@@ -509,11 +616,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 +634,6 @@ public class DependencyCheckScanAgent {
|
||||
this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of the Nexus server.
|
||||
*/
|
||||
private String nexusUrl;
|
||||
|
||||
/**
|
||||
* Get the value of nexusUrl.
|
||||
*
|
||||
@@ -555,11 +652,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 +670,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 +688,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 +706,6 @@ public class DependencyCheckScanAgent {
|
||||
this.databaseDriverPath = databaseDriverPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* The database connection string.
|
||||
*/
|
||||
private String connectionString;
|
||||
|
||||
/**
|
||||
* Get the value of connectionString.
|
||||
*
|
||||
@@ -647,11 +724,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 +742,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 +760,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 +778,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 +796,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 +814,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 +832,6 @@ public class DependencyCheckScanAgent {
|
||||
this.cveUrl12Base = cveUrl12Base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data Mirror URL for CVE 2.0.
|
||||
*/
|
||||
private String cveUrl20Base;
|
||||
|
||||
/**
|
||||
* Get the value of cveUrl20Base.
|
||||
*
|
||||
@@ -809,11 +850,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.
|
||||
*
|
||||
@@ -833,17 +869,52 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the Dependency-Check on the dependent libraries.
|
||||
* Get the value of propertiesFilePath.
|
||||
*
|
||||
* @return the value of propertiesFilePath
|
||||
*/
|
||||
public String getPropertiesFilePath() {
|
||||
return propertiesFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of propertiesFilePath.
|
||||
*
|
||||
* @param propertiesFilePath new value of propertiesFilePath
|
||||
*/
|
||||
public void setPropertiesFilePath(String propertiesFilePath) {
|
||||
this.propertiesFilePath = propertiesFilePath;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* Executes the Dependency-Check on the dependent libraries. <b>Note</b>, the engine
|
||||
* object returned from this method must be closed by calling `close()`
|
||||
*
|
||||
* @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();
|
||||
engine.setDependencies(this.dependencies);
|
||||
engine.analyzeDependencies();
|
||||
final Engine engine;
|
||||
try {
|
||||
engine = new Engine(settings);
|
||||
} catch (DatabaseException ex) {
|
||||
throw new ExceptionCollection(ex, true);
|
||||
}
|
||||
if (this.updateOnly) {
|
||||
try {
|
||||
engine.doUpdates();
|
||||
} catch (UpdateException ex) {
|
||||
throw new ExceptionCollection("Unable to perform update", ex);
|
||||
} finally {
|
||||
engine.close();
|
||||
}
|
||||
} else {
|
||||
engine.setDependencies(this.dependencies);
|
||||
engine.analyzeDependencies();
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
||||
@@ -852,155 +923,116 @@ public class DependencyCheckScanAgent {
|
||||
*
|
||||
* @param engine a dependency-check engine
|
||||
* @param outDirectory the directory to write the reports to
|
||||
* @throws 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();
|
||||
settings = new Settings();
|
||||
if (dataDirectory != null) {
|
||||
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
|
||||
settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
|
||||
} else {
|
||||
final File jarPath = new File(DependencyCheckScanAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath());
|
||||
final File base = jarPath.getParentFile();
|
||||
final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
|
||||
final String sub = settings.getString(Settings.KEYS.DATA_DIRECTORY);
|
||||
final File dataDir = new File(base, sub);
|
||||
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
|
||||
settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
|
||||
}
|
||||
if (propertiesFilePath != null) {
|
||||
try {
|
||||
settings.mergeProperties(propertiesFilePath);
|
||||
LOGGER.info("Successfully loaded user-defined properties");
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Unable to merge user-defined properties", e);
|
||||
LOGGER.error("Continuing execution");
|
||||
}
|
||||
}
|
||||
|
||||
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.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||
if (centralUrl != null && !centralUrl.isEmpty()) {
|
||||
Settings.setString(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.setBoolean(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, proxyUsername);
|
||||
settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
|
||||
settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
|
||||
settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
|
||||
settings.setStringIfNotEmpty(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER, cpeStartsWithFilter);
|
||||
settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_URL, centralUrl);
|
||||
settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
||||
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;
|
||||
try {
|
||||
engine = executeDependencyCheck();
|
||||
if (this.generateReport) {
|
||||
generateExternalReports(engine, new File(this.reportOutputDirectory));
|
||||
if (!this.updateOnly) {
|
||||
if (this.generateReport) {
|
||||
generateExternalReports(engine, new File(this.reportOutputDirectory));
|
||||
}
|
||||
if (this.showSummary) {
|
||||
showSummary(engine.getDependencies());
|
||||
}
|
||||
if (this.failBuildOnCVSS <= 10) {
|
||||
checkForFailure(engine.getDependencies());
|
||||
}
|
||||
}
|
||||
if (this.showSummary) {
|
||||
showSummary(engine.getDependencies());
|
||||
} 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);
|
||||
}
|
||||
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);
|
||||
throw new ScanAgentException("One or more exceptions occurred during analysis; please see the debug log for more details.", ex);
|
||||
} finally {
|
||||
Settings.cleanup(true);
|
||||
settings.cleanup(true);
|
||||
if (engine != null) {
|
||||
engine.cleanup();
|
||||
engine.close();
|
||||
}
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
private void checkForFailure(Dependency[] dependencies) throws ScanAgentException {
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean addName = true;
|
||||
@@ -1017,25 +1049,32 @@ 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"
|
||||
+ "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
|
||||
|
||||
final String msg;
|
||||
if (showSummary) {
|
||||
msg = String.format("%n%nDependency-Check Failure:%n"
|
||||
+ "One or more dependencies were identified with vulnerabilities that have a CVSS score greater than or equal to '%.1f': %s%n"
|
||||
+ "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
|
||||
} else {
|
||||
msg = String.format("%n%nDependency-Check Failure:%n"
|
||||
+ "One or more dependencies were identified with vulnerabilities.%n%n"
|
||||
+ "See the dependency-check report for more details.%n%n");
|
||||
}
|
||||
throw new ScanAgentException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private void showSummary(List<Dependency> dependencies) {
|
||||
private void showSummary(Dependency[] dependencies) {
|
||||
final StringBuilder summary = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean firstEntry = true;
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
for (Vulnerability v : d.getVulnerabilities(true)) {
|
||||
if (firstEntry) {
|
||||
firstEntry = false;
|
||||
} else {
|
||||
@@ -1063,5 +1102,4 @@ public class DependencyCheckScanAgent {
|
||||
summary.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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 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 javax.annotation.concurrent.ThreadSafe;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Base class for analyzers to avoid code duplication of prepare and close as
|
||||
* most analyzers do not need these methods.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractAnalyzer implements 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;
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private Settings settings;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured settings.
|
||||
*
|
||||
* @return the configured settings
|
||||
*/
|
||||
protected Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the analyzer with the configured settings.
|
||||
*
|
||||
* @param settings the configured settings to use
|
||||
*/
|
||||
@Override
|
||||
public void initialize(Settings settings) {
|
||||
this.settings = settings;
|
||||
final String key = getAnalyzerEnabledSettingKey();
|
||||
try {
|
||||
this.setEnabled(settings.getBoolean(key, true));
|
||||
} catch (InvalidSettingException ex) {
|
||||
final String msg = String.format("Invalid setting for property '%s'", key);
|
||||
LOGGER.warn(msg);
|
||||
LOGGER.debug(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the abstract analyzer.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if there is an exception
|
||||
*/
|
||||
@Override
|
||||
public final void prepare(Engine engine) throws InitializationException {
|
||||
if (isEnabled()) {
|
||||
prepareAnalyzer(engine);
|
||||
} else {
|
||||
LOGGER.debug("{} has been disabled", getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a given Analyzer. This will be skipped if the analyzer is
|
||||
* disabled.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if there is an exception
|
||||
*/
|
||||
protected void prepareAnalyzer(Engine engine) throws InitializationException {
|
||||
// Intentionally empty, analyzer will override this if they must prepare anything.
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (this.isEnabled()) {
|
||||
analyzeDependency(dependency, engine);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The close method does nothing for this Analyzer.
|
||||
*
|
||||
* @throws Exception thrown if there is an exception
|
||||
*/
|
||||
@Override
|
||||
public final void close() throws Exception {
|
||||
if (isEnabled()) {
|
||||
closeAnalyzer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
}
|
||||
|
||||
/**
|
||||
* The default is to support parallel processing.
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParallelProcessing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
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>
|
||||
* <p>
|
||||
* Note, this grouping only works on dependencies with identified CVE
|
||||
* entries</p>
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractDependencyComparingAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDependencyComparingAnalyzer.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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final boolean supportsParallelProcessing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException {
|
||||
if (!analyzed) {
|
||||
analyzed = true;
|
||||
final Set<Dependency> dependenciesToRemove = new HashSet<>();
|
||||
|
||||
final Dependency[] dependencies = engine.getDependencies();
|
||||
if (dependencies.length < 2) {
|
||||
return;
|
||||
}
|
||||
for (int x = 0; x < dependencies.length - 1; x++) {
|
||||
final Dependency dependency = dependencies[x];
|
||||
if (!dependenciesToRemove.contains(dependency)) {
|
||||
for (int y = x + 1; y < dependencies.length; y++) {
|
||||
final Dependency nextDependency = dependencies[y];
|
||||
if (evaluateDependencies(dependency, nextDependency, dependenciesToRemove)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Dependency d : dependenciesToRemove) {
|
||||
engine.removeDependency(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the dependencies
|
||||
*
|
||||
* @param dependency a dependency to compare
|
||||
* @param nextDependency a dependency to compare
|
||||
* @param dependenciesToRemove a set of dependencies that will be removed
|
||||
* @return true if a dependency is removed; otherwise false
|
||||
*/
|
||||
protected abstract boolean evaluateDependencies(final Dependency dependency,
|
||||
final Dependency nextDependency, final Set<Dependency> dependenciesToRemove);
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
|
||||
/**
|
||||
* The base FileTypeAnalyzer that all analyzers that have specific file types
|
||||
* they analyze should extend.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implements FileTypeAnalyzer {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Field definitions, getters, and setters ">
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFileTypeAnalyzer.class);
|
||||
/**
|
||||
* Whether the file type analyzer detected any files it needs to analyze.
|
||||
*/
|
||||
private boolean filesMatched = false;
|
||||
|
||||
/**
|
||||
* Set the value of filesMatched. A flag indicating whether the scan
|
||||
* included any file types this analyzer supports.
|
||||
*
|
||||
* @param filesMatched new value of filesMatched
|
||||
*/
|
||||
protected void setFilesMatched(boolean filesMatched) {
|
||||
this.filesMatched = filesMatched;
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
//<editor-fold defaultstate="collapsed" desc="Final implementations for the Analyzer interface">
|
||||
/**
|
||||
* Initializes the analyzer.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if there is an exception during
|
||||
* initialization
|
||||
*/
|
||||
@Override
|
||||
protected final void prepareAnalyzer(Engine engine) throws InitializationException {
|
||||
if (filesMatched) {
|
||||
prepareFileTypeAnalyzer(engine);
|
||||
} else {
|
||||
this.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
//</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>
|
||||
* <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
|
||||
*/
|
||||
protected abstract FileFilter getFileFilter();
|
||||
|
||||
/**
|
||||
* Prepares the file type analyzer for dependency analysis.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if there is an exception during
|
||||
* initialization
|
||||
*/
|
||||
protected abstract void prepareFileTypeAnalyzer(Engine engine) throws InitializationException;
|
||||
|
||||
//</editor-fold>
|
||||
/**
|
||||
* Determines if the file can be analyzed by the analyzer.
|
||||
*
|
||||
* @param pathname the path to the file
|
||||
* @return true if the file can be analyzed by the given analyzer; otherwise
|
||||
* false
|
||||
*/
|
||||
@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 (this.isEnabled()) {
|
||||
accepted = filter.accept(pathname);
|
||||
if (accepted) {
|
||||
filesMatched = true;
|
||||
}
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* <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/prepare-java-hashset-values-by-construction</p>
|
||||
*
|
||||
* @param strings a list of strings to add to the set.
|
||||
* @return a Set of strings.
|
||||
*/
|
||||
protected static Set<String> newHashSet(String... strings) {
|
||||
final Set<String> set = new HashSet<>(strings.length);
|
||||
Collections.addAll(set, strings);
|
||||
return set;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* 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 Steve Springett. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.dependency.Confidence;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonArray;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonObjectBuilder;
|
||||
import javax.json.JsonString;
|
||||
import javax.json.JsonValue;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.dependency.EvidenceType;
|
||||
import org.owasp.dependencycheck.utils.Checksum;
|
||||
|
||||
/**
|
||||
* An abstract NPM analyzer that contains common methods for concrete
|
||||
* implementations.
|
||||
*
|
||||
* @author Steve Springett
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractNpmAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNpmAnalyzer.class);
|
||||
|
||||
/**
|
||||
* A descriptor for the type of dependencies processed or added by this
|
||||
* analyzer.
|
||||
*/
|
||||
public static final String NPM_DEPENDENCY_ECOSYSTEM = "npm";
|
||||
/**
|
||||
* The file name to scan.
|
||||
*/
|
||||
private static final String PACKAGE_JSON = "package.json";
|
||||
|
||||
/**
|
||||
* Determines if the file can be analyzed by the analyzer.
|
||||
*
|
||||
* @param pathname the path to the file
|
||||
* @return true if the file can be analyzed by the given analyzer; otherwise
|
||||
* false
|
||||
*/
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
boolean accept = super.accept(pathname);
|
||||
if (accept) {
|
||||
try {
|
||||
accept |= shouldProcess(pathname);
|
||||
} catch (AnalysisException ex) {
|
||||
throw new RuntimeException(ex.getMessage(), ex.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
return accept;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the path contains "/node_modules/" (i.e. it is a child
|
||||
* module. This analyzer does not scan child modules.
|
||||
*
|
||||
* @param pathname the path to test
|
||||
* @return <code>true</code> if the path does not contain "/node_modules/"
|
||||
* @throws AnalysisException thrown if the canonical path cannot be obtained
|
||||
* from the given file
|
||||
*/
|
||||
protected boolean shouldProcess(File pathname) throws AnalysisException {
|
||||
try {
|
||||
// Do not scan the node_modules directory
|
||||
if (pathname.getCanonicalPath().contains(File.separator + "node_modules" + File.separator)) {
|
||||
LOGGER.debug("Skipping analysis of node module: " + pathname.getCanonicalPath());
|
||||
return false;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new AnalysisException("Unable to process dependency", ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a dependency object.
|
||||
*
|
||||
* @param dependency the parent dependency
|
||||
* @param name the name of the dependency to create
|
||||
* @param version the version of the dependency to create
|
||||
* @param scope the scope of the dependency being created
|
||||
* @return the generated dependency
|
||||
*/
|
||||
protected Dependency createDependency(Dependency dependency, String name, String version, String scope) {
|
||||
final Dependency nodeModule = new Dependency(new File(dependency.getActualFile() + "?" + name), true);
|
||||
nodeModule.setEcosystem(NPM_DEPENDENCY_ECOSYSTEM);
|
||||
//this is virtual - the sha1 is purely for the hyperlink in the final html report
|
||||
nodeModule.setSha1sum(Checksum.getSHA1Checksum(String.format("%s:%s", name, version)));
|
||||
nodeModule.setMd5sum(Checksum.getMD5Checksum(String.format("%s:%s", name, version)));
|
||||
nodeModule.addEvidence(EvidenceType.PRODUCT, "package.json", "name", name, Confidence.HIGHEST);
|
||||
nodeModule.addEvidence(EvidenceType.VENDOR, "package.json", "name", name, Confidence.HIGH);
|
||||
nodeModule.addEvidence(EvidenceType.VERSION, "package.json", "version", version, Confidence.HIGHEST);
|
||||
nodeModule.addProjectReference(dependency.getName() + ": " + scope);
|
||||
nodeModule.setName(name);
|
||||
nodeModule.setVersion(version);
|
||||
nodeModule.addIdentifier("npm", String.format("%s:%s", name, version), null, Confidence.HIGHEST);
|
||||
return nodeModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a part of package.json (as defined by JsonArray) and update the
|
||||
* specified dependency with relevant info.
|
||||
*
|
||||
* @param engine the dependency-check engine
|
||||
* @param dependency the Dependency to update
|
||||
* @param jsonArray the jsonArray to parse
|
||||
* @param depType the dependency type
|
||||
*/
|
||||
protected void processPackage(Engine engine, Dependency dependency, JsonArray jsonArray, String depType) {
|
||||
final JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||
for (JsonString str : jsonArray.getValuesAs(JsonString.class)) {
|
||||
builder.add(str.toString(), "");
|
||||
}
|
||||
final JsonObject jsonObject = builder.build();
|
||||
processPackage(engine, dependency, jsonObject, depType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a part of package.json (as defined by JsonObject) and update
|
||||
* the specified dependency with relevant info.
|
||||
*
|
||||
* @param engine the dependency-check engine
|
||||
* @param dependency the Dependency to update
|
||||
* @param jsonObject the jsonObject to parse
|
||||
* @param depType the dependency type
|
||||
*/
|
||||
protected void processPackage(Engine engine, Dependency dependency, JsonObject jsonObject, String depType) {
|
||||
for (int i = 0; i < jsonObject.size(); i++) {
|
||||
for (Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
|
||||
|
||||
final String name = entry.getKey();
|
||||
String version = "";
|
||||
if (entry.getValue() != null && entry.getValue().getValueType() == JsonValue.ValueType.STRING) {
|
||||
version = ((JsonString) entry.getValue()).getString();
|
||||
}
|
||||
final Dependency existing = findDependency(engine, name, version);
|
||||
if (existing == null) {
|
||||
final Dependency nodeModule = createDependency(dependency, name, version, depType);
|
||||
engine.addDependency(nodeModule);
|
||||
} else {
|
||||
existing.addProjectReference(dependency.getName() + ": " + depType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds information to an evidence collection from the node json
|
||||
* configuration.
|
||||
*
|
||||
* @param dep the dependency to add the evidence
|
||||
* @param t the type of evidence to add
|
||||
* @param json information from node.js
|
||||
* @return the actual string set into evidence
|
||||
* @param key the key to obtain the data from the json information
|
||||
*/
|
||||
private static String addToEvidence(Dependency dep, EvidenceType t, JsonObject json, String key) {
|
||||
String evidenceStr = null;
|
||||
if (json.containsKey(key)) {
|
||||
final JsonValue value = json.get(key);
|
||||
if (value instanceof JsonString) {
|
||||
evidenceStr = ((JsonString) value).getString();
|
||||
dep.addEvidence(t, PACKAGE_JSON, key, evidenceStr, 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) {
|
||||
evidenceStr = ((JsonString) subValue).getString();
|
||||
dep.addEvidence(t, PACKAGE_JSON,
|
||||
String.format("%s.%s", key, property),
|
||||
evidenceStr,
|
||||
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);
|
||||
}
|
||||
}
|
||||
return evidenceStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the dependency from the list of dependencies that have been
|
||||
* scanned by the engine.
|
||||
*
|
||||
* @param engine the dependency-check engine
|
||||
* @param name the name of the dependency to find
|
||||
* @param version the version of the dependency to find
|
||||
* @return the identified dependency; otherwise null
|
||||
*/
|
||||
protected Dependency findDependency(Engine engine, String name, String version) {
|
||||
for (Dependency d : engine.getDependencies()) {
|
||||
if (NPM_DEPENDENCY_ECOSYSTEM.equals(d.getEcosystem()) && name.equals(d.getName()) && version != null && d.getVersion() != null) {
|
||||
final String dependencyVersion = d.getVersion();
|
||||
if (DependencyBundlingAnalyzer.npmVersionsMatch(version, dependencyVersion)) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects evidence from the given JSON for the associated dependency.
|
||||
*
|
||||
* @param json the JSON that contains the evidence to collect
|
||||
* @param dependency the dependency to add the evidence too
|
||||
*/
|
||||
public void gatherEvidence(final JsonObject json, Dependency dependency) {
|
||||
if (json.containsKey("name")) {
|
||||
final Object value = json.get("name");
|
||||
if (value instanceof JsonString) {
|
||||
final String valueString = ((JsonString) value).getString();
|
||||
dependency.setName(valueString);
|
||||
dependency.setPackagePath(valueString);
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, PACKAGE_JSON, "name", valueString, Confidence.HIGHEST);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, PACKAGE_JSON, "name", valueString, Confidence.HIGH);
|
||||
} else {
|
||||
LOGGER.warn("JSON value not string as expected: {}", value);
|
||||
}
|
||||
}
|
||||
final String desc = addToEvidence(dependency, EvidenceType.PRODUCT, json, "description");
|
||||
dependency.setDescription(desc);
|
||||
addToEvidence(dependency, EvidenceType.VENDOR, json, "author");
|
||||
final String version = addToEvidence(dependency, EvidenceType.VERSION, json, "version");
|
||||
if (version != null) {
|
||||
dependency.setVersion(version);
|
||||
dependency.addIdentifier("npm", String.format("%s:%s", dependency.getName(), version), null, Confidence.HIGHEST);
|
||||
}
|
||||
|
||||
// Adds the license if defined in package.json
|
||||
if (json.containsKey("license")) {
|
||||
final Object value = json.get("license");
|
||||
if (value instanceof JsonString) {
|
||||
dependency.setLicense(json.getString("license"));
|
||||
} else if (value instanceof JsonArray) {
|
||||
final JsonArray array = (JsonArray) value;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
boolean addComma = false;
|
||||
for (int x = 0; x < array.size(); x++) {
|
||||
if (!array.isNull(x)) {
|
||||
if (addComma) {
|
||||
sb.append(", ");
|
||||
} else {
|
||||
addComma = true;
|
||||
}
|
||||
sb.append(array.getString(x));
|
||||
}
|
||||
}
|
||||
dependency.setLicense(sb.toString());
|
||||
} else {
|
||||
dependency.setLicense(json.getJsonObject("license").getString("type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
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.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
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.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.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger for use throughout the class.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSuppressionAnalyzer.class);
|
||||
/**
|
||||
* The list of suppression rules.
|
||||
*/
|
||||
private List<SuppressionRule> rules = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Get the number of suppression rules.
|
||||
*
|
||||
* @return the number of suppression rules
|
||||
*/
|
||||
protected int getRuleCount() {
|
||||
return rules.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of file EXTENSIONS supported by this analyzer.
|
||||
*
|
||||
* @return a list of file EXTENSIONS supported by this analyzer.
|
||||
*/
|
||||
public Set<String> getSupportedExtensions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The prepare method loads the suppression XML file.
|
||||
*
|
||||
* @param engine a reference the dependency-check engine
|
||||
* @throws InitializationException thrown if there is an exception
|
||||
*/
|
||||
@Override
|
||||
public synchronized void prepareAnalyzer(Engine engine) throws InitializationException {
|
||||
if (rules.isEmpty()) {
|
||||
try {
|
||||
loadSuppressionBaseData();
|
||||
} catch (SuppressionParseException ex) {
|
||||
throw new InitializationException("Error initializing the suppression analyzer: " + ex.getLocalizedMessage(), ex, true);
|
||||
}
|
||||
|
||||
try {
|
||||
loadSuppressionData();
|
||||
} catch (SuppressionParseException ex) {
|
||||
throw new InitializationException("Warn initializing the suppression analyzer: " + ex.getLocalizedMessage(), ex, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
if (rules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (final SuppressionRule rule : rules) {
|
||||
rule.process(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all the suppression rules files configured in the {@link Settings}.
|
||||
*
|
||||
* @throws SuppressionParseException thrown if the XML cannot be parsed.
|
||||
*/
|
||||
private void loadSuppressionData() throws SuppressionParseException {
|
||||
final List<SuppressionRule> ruleList = new ArrayList<>();
|
||||
final SuppressionParser parser = new SuppressionParser();
|
||||
final String[] suppressionFilePaths = getSettings().getArray(Settings.KEYS.SUPPRESSION_FILE);
|
||||
final List<String> failedLoadingFiles = new ArrayList<>();
|
||||
if (suppressionFilePaths != null && suppressionFilePaths.length > 0) {
|
||||
// Load all the suppression file paths
|
||||
for (final String suppressionFilePath : suppressionFilePaths) {
|
||||
try {
|
||||
ruleList.addAll(loadSuppressionFile(parser, suppressionFilePath));
|
||||
} catch (SuppressionParseException ex) {
|
||||
final String msg = String.format("Failed to load %s, caused by %s. ", suppressionFilePath, ex.getMessage());
|
||||
failedLoadingFiles.add(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.debug("{} suppression rules were loaded.", ruleList.size());
|
||||
rules.addAll(ruleList);
|
||||
if (!failedLoadingFiles.isEmpty()) {
|
||||
LOGGER.debug("{} suppression files failed to load.", failedLoadingFiles.size());
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (String item : failedLoadingFiles) {
|
||||
sb.append(item);
|
||||
}
|
||||
throw new SuppressionParseException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all the base suppression rules files.
|
||||
*
|
||||
* @throws SuppressionParseException thrown if the XML cannot be parsed.
|
||||
*/
|
||||
private void loadSuppressionBaseData() throws SuppressionParseException {
|
||||
final SuppressionParser parser = new SuppressionParser();
|
||||
List<SuppressionRule> ruleList;
|
||||
try {
|
||||
final InputStream in = FileUtils.getResourceAsStream("dependencycheck-base-suppression.xml");
|
||||
ruleList = parser.parseSuppressionRules(in);
|
||||
} catch (SAXException ex) {
|
||||
throw new SuppressionParseException("Unable to parse the base suppression data file", ex);
|
||||
}
|
||||
rules.addAll(ruleList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single suppression rules file from the path provided using the
|
||||
* parser provided.
|
||||
*
|
||||
* @param parser the parser to use for loading the file
|
||||
* @param suppressionFilePath the path to load
|
||||
* @return the list of loaded suppression rules
|
||||
* @throws SuppressionParseException thrown if the suppression file cannot
|
||||
* be loaded and parsed.
|
||||
*/
|
||||
private List<SuppressionRule> loadSuppressionFile(final SuppressionParser parser,
|
||||
final String suppressionFilePath) throws SuppressionParseException {
|
||||
LOGGER.debug("Loading suppression rules from '{}'", suppressionFilePath);
|
||||
final List<SuppressionRule> list = new ArrayList<>();
|
||||
File file = null;
|
||||
boolean deleteTempFile = false;
|
||||
try {
|
||||
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
|
||||
if (uriRx.matcher(suppressionFilePath).matches()) {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("suppression", "xml");
|
||||
final URL url = new URL(suppressionFilePath);
|
||||
final Downloader downloader = new Downloader(getSettings());
|
||||
try {
|
||||
downloader.fetchFile(url, file, false);
|
||||
} catch (DownloadFailedException ex) {
|
||||
LOGGER.trace("Failed download - first attempt", ex);
|
||||
downloader.fetchFile(url, file, true);
|
||||
}
|
||||
} else {
|
||||
file = new File(suppressionFilePath);
|
||||
|
||||
if (!file.exists()) {
|
||||
try (InputStream suppressionsFromClasspath = FileUtils.getResourceAsStream(suppressionFilePath)) {
|
||||
if (suppressionsFromClasspath != null) {
|
||||
deleteTempFile = true;
|
||||
file = getSettings().getTempFile("suppression", "xml");
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
|
||||
} catch (IOException ex) {
|
||||
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex, suppressionFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (file != null) {
|
||||
if (!file.exists()) {
|
||||
final String msg = String.format("Suppression file '%s' does not exist", file.getPath());
|
||||
LOGGER.warn(msg);
|
||||
throw new SuppressionParseException(msg);
|
||||
}
|
||||
try {
|
||||
list.addAll(parser.parseSuppressionRules(file));
|
||||
} catch (SuppressionParseException ex) {
|
||||
LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
|
||||
LOGGER.warn(ex.getMessage());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} catch (DownloadFailedException ex) {
|
||||
throwSuppressionParseException("Unable to fetch the configured suppression file", ex, suppressionFilePath);
|
||||
} catch (MalformedURLException ex) {
|
||||
throwSuppressionParseException("Configured suppression file has an invalid URL", ex, suppressionFilePath);
|
||||
} catch (SuppressionParseException ex) {
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
throwSuppressionParseException("Unable to create temp file for suppressions", ex, suppressionFilePath);
|
||||
} finally {
|
||||
if (deleteTempFile && file != null) {
|
||||
FileUtils.delete(file);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to throw parse exceptions.
|
||||
*
|
||||
* @param message the exception message
|
||||
* @param exception the cause of the exception
|
||||
* @param suppressionFilePath the path file
|
||||
* @throws SuppressionParseException throws the generated
|
||||
* SuppressionParseException
|
||||
*/
|
||||
private void throwSuppressionParseException(String message, Exception exception, String suppressionFilePath) throws SuppressionParseException {
|
||||
LOGGER.warn(String.format(message + "'%s'", suppressionFilePath));
|
||||
LOGGER.debug("", exception);
|
||||
throw new SuppressionParseException(message, exception);
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 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.Settings;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.</p>
|
||||
* <p>
|
||||
* When the {@link org.owasp.dependencycheck.Engine} executes it will load the
|
||||
* analyzers and call the methods in the following order:</p>
|
||||
* <ol>
|
||||
* <li>{@link #initialize(org.owasp.dependencycheck.utils.Settings)}</li>
|
||||
* <li>{@link #prepare(org.owasp.dependencycheck.Engine)}</li>
|
||||
* <li>{@link #analyze(org.owasp.dependencycheck.dependency.Dependency, org.owasp.dependencycheck.Engine)}</li>
|
||||
* <li>{@link #close()}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
void analyze(Dependency dependency, Engine engine) throws AnalysisException;
|
||||
|
||||
/**
|
||||
* Returns the name of the analyzer.
|
||||
*
|
||||
* @return the name of the analyzer.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns the phase that the analyzer is intended to run in.
|
||||
*
|
||||
* @return the phase that the analyzer is intended to run in.
|
||||
*/
|
||||
AnalysisPhase getAnalysisPhase();
|
||||
|
||||
/**
|
||||
* Initializes the analyzer with the configured settings.
|
||||
*
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
void initialize(Settings settings);
|
||||
|
||||
/**
|
||||
* The prepare method is called (once) prior to the analyze method being
|
||||
* called on all of the dependencies.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException is thrown if an exception occurs
|
||||
* initializing the analyzer.
|
||||
*/
|
||||
void prepare(Engine engine) throws InitializationException;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* The Analyzer Service Loader. This class loads all services that implement
|
||||
* {@link org.owasp.dependencycheck.analyzer.Analyzer}.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
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> service;
|
||||
/**
|
||||
* The configured settings.
|
||||
*/
|
||||
private final Settings settings;
|
||||
|
||||
/**
|
||||
* Creates a new instance of AnalyzerService.
|
||||
*
|
||||
* @param classLoader the ClassLoader to use when dynamically loading
|
||||
* Analyzer and Update services
|
||||
* @param settings the configured settings
|
||||
*/
|
||||
public AnalyzerService(ClassLoader classLoader, Settings settings) {
|
||||
service = ServiceLoader.load(Analyzer.class, classLoader);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all instances of the Analyzer interface.
|
||||
*
|
||||
* @return a list of Analyzers.
|
||||
*/
|
||||
public List<Analyzer> getAnalyzers() {
|
||||
return getAnalyzers(AnalysisPhase.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all instances of the Analyzer interface that are bound
|
||||
* to one of the given phases.
|
||||
*
|
||||
* @param phases the phases to obtain analyzers for
|
||||
* @return a list of Analyzers.
|
||||
*/
|
||||
public List<Analyzer> getAnalyzers(AnalysisPhase... phases) {
|
||||
return getAnalyzers(asList(phases));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all instances of the Analyzer interface that are bound
|
||||
* to one of the given phases.
|
||||
*
|
||||
* @param phases the phases to obtain analyzers for
|
||||
* @return a list of Analyzers
|
||||
*/
|
||||
private List<Analyzer> getAnalyzers(List<AnalysisPhase> phases) {
|
||||
final List<Analyzer> analyzers = new ArrayList<>();
|
||||
final Iterator<Analyzer> iterator = service.iterator();
|
||||
boolean experimentalEnabled = false;
|
||||
boolean retiredEnabled = false;
|
||||
try {
|
||||
experimentalEnabled = settings.getBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false);
|
||||
retiredEnabled = settings.getBoolean(Settings.KEYS.ANALYZER_RETIRED_ENABLED, false);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.error("invalid experimental or retired setting", ex);
|
||||
}
|
||||
while (iterator.hasNext()) {
|
||||
final Analyzer a = iterator.next();
|
||||
if (!phases.contains(a.getAnalysisPhase())) {
|
||||
continue;
|
||||
}
|
||||
if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
|
||||
continue;
|
||||
}
|
||||
if (!retiredEnabled && a.getClass().isAnnotationPresent(Retired.class)) {
|
||||
continue;
|
||||
}
|
||||
LOGGER.debug("Loaded Analyzer {}", a.getName());
|
||||
analyzers.add(a);
|
||||
}
|
||||
return analyzers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,625 @@
|
||||
/*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
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.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
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>
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class);
|
||||
/**
|
||||
* The count of directories created during analysis. This is used for
|
||||
* creating temporary directories.
|
||||
*/
|
||||
private static final AtomicInteger DIRECTORY_COUNT = new AtomicInteger(0);
|
||||
/**
|
||||
* The parent directory for the individual directories per archive.
|
||||
*/
|
||||
private File tempFileLocation = null;
|
||||
/**
|
||||
* The max scan depth that the analyzer will recursively extract nested
|
||||
* archives.
|
||||
*/
|
||||
private int maxScanDepth;
|
||||
/**
|
||||
* The file filter used to filter supported files.
|
||||
*/
|
||||
private FileFilter fileFilter = null;
|
||||
/**
|
||||
* The set of things we can handle with Zip methods
|
||||
*/
|
||||
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 {@link #extractFiles(File, File, Engine)}.
|
||||
*/
|
||||
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2");
|
||||
|
||||
/**
|
||||
* 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();
|
||||
/**
|
||||
* Detects files with .zip extension.
|
||||
*/
|
||||
private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build();
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
*/
|
||||
private static final String ANALYZER_NAME = "Archive Analyzer";
|
||||
/**
|
||||
* The phase that this analyzer is intended to run in.
|
||||
*/
|
||||
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
|
||||
|
||||
/**
|
||||
* Initializes the analyzer with the configured settings.
|
||||
*
|
||||
* @param settings the configured settings to use
|
||||
*/
|
||||
@Override
|
||||
public void initialize(Settings settings) {
|
||||
super.initialize(settings);
|
||||
initializeSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FileFilter getFileFilter() {
|
||||
return fileFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* 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_ARCHIVE_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* The prepare method does nothing for this Analyzer.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException is thrown if there is an exception
|
||||
* deleting or creating temporary files
|
||||
*/
|
||||
@Override
|
||||
public void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
|
||||
try {
|
||||
final File baseDir = getSettings().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.
|
||||
*
|
||||
* @throws Exception thrown if there is an exception deleting temporary
|
||||
* files
|
||||
*/
|
||||
@Override
|
||||
public void closeAnalyzer() throws Exception {
|
||||
if (tempFileLocation != null && tempFileLocation.exists()) {
|
||||
LOGGER.debug("Attempting to delete temporary files from `{}`", tempFileLocation.toString());
|
||||
final boolean success = FileUtils.delete(tempFileLocation);
|
||||
if (!success && tempFileLocation.exists()) {
|
||||
final String[] l = tempFileLocation.list();
|
||||
if (l != null && l.length > 0) {
|
||||
LOGGER.warn("Failed to delete the Archive Analyzer's temporary files from `{}`, "
|
||||
+ "see the log for more details", tempFileLocation.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
extractAndAnalyze(dependency, engine, 0);
|
||||
engine.sortDependencies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the contents of the archive dependency and scans for additional
|
||||
* dependencies.
|
||||
*
|
||||
* @param dependency the dependency being analyzed
|
||||
* @param engine the engine doing the analysis
|
||||
* @param scanDepth the current scan depth; extracctAndAnalyze is recursive
|
||||
* and will, be default, only go 3 levels deep
|
||||
* @throws AnalysisException thrown if there is a problem analyzing the
|
||||
* dependencies
|
||||
*/
|
||||
private void extractAndAnalyze(Dependency dependency, Engine engine, int scanDepth) throws AnalysisException {
|
||||
final File f = new File(dependency.getActualFilePath());
|
||||
final File tmpDir = getNextTempDirectory();
|
||||
extractFiles(f, tmpDir, engine);
|
||||
|
||||
//make a copy
|
||||
final List<Dependency> dependencySet = findMoreDependencies(engine, tmpDir);
|
||||
|
||||
if (dependencySet != null && !dependencySet.isEmpty()) {
|
||||
for (Dependency d : dependencySet) {
|
||||
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.addAllProjectReferences(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 < maxScanDepth) {
|
||||
extractAndAnalyze(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())) {
|
||||
addDisguisedJarsToDependencies(dependency, engine);
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return a directory
|
||||
* @throws AnalysisException thrown if unable to create temporary directory
|
||||
*/
|
||||
private File getNextTempDirectory() throws AnalysisException {
|
||||
final File directory = new File(tempFileLocation, String.valueOf(DIRECTORY_COUNT.incrementAndGet()));
|
||||
//getting an exception for some directories not being able to be created; might be because the directory already exists?
|
||||
if (directory.exists()) {
|
||||
return getNextTempDirectory();
|
||||
}
|
||||
if (!directory.mkdirs()) {
|
||||
final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
|
||||
throw new AnalysisException(msg);
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the contents of an archive into the specified directory.
|
||||
*
|
||||
* @param archive an archive file such as a WAR or EAR
|
||||
* @param destination a directory to extract the contents to
|
||||
* @param engine the scanning engine
|
||||
* @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) {
|
||||
String archiveExt = FileUtils.getFileExtension(archive.getName());
|
||||
if (archiveExt == null) {
|
||||
return;
|
||||
}
|
||||
archiveExt = archiveExt.toLowerCase();
|
||||
|
||||
final FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream(archive);
|
||||
} catch (FileNotFoundException ex) {
|
||||
final String msg = String.format("Error extracting file `%s`: %s", archive.getAbsolutePath(), ex.getMessage());
|
||||
LOGGER.debug(msg, ex);
|
||||
throw new AnalysisException(msg);
|
||||
}
|
||||
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;
|
||||
//CSOFF: InnerAssignment
|
||||
//CSOFF: NestedIfDepth
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//CSON: InnerAssignment
|
||||
//CSON: NestedIfDepth
|
||||
} else {
|
||||
in.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts files from an archive.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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()) {
|
||||
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 | AnalysisException ex) {
|
||||
throw new ArchiveExtractionException(ex);
|
||||
} finally {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses a file.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
|
||||
LOGGER.debug("Decompressing '{}'", outputFile.getPath());
|
||||
try (FileOutputStream out = new FileOutputStream(outputFile)) {
|
||||
IOUtils.copy(inputStream, out);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.debug("", ex);
|
||||
throw new ArchiveExtractionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to determine if a zip file is actually a JAR file.
|
||||
*
|
||||
* @param dependency the dependency to check
|
||||
* @return true if the dependency appears to be a JAR file; otherwise false
|
||||
*/
|
||||
private boolean isZipFileActuallyJarFile(Dependency dependency) {
|
||||
boolean isJar = false;
|
||||
ZipFile zip = null;
|
||||
try {
|
||||
zip = new ZipFile(dependency.getActualFilePath());
|
||||
if (zip.getEntry("META-INF/MANIFEST.MF") != null
|
||||
|| zip.getEntry("META-INF/maven") != null) {
|
||||
final Enumeration<ZipArchiveEntry> entries = zip.getEntries();
|
||||
while (entries.hasMoreElements()) {
|
||||
final ZipArchiveEntry entry = entries.nextElement();
|
||||
if (!entry.isDirectory()) {
|
||||
final String name = entry.getName().toLowerCase();
|
||||
if (name.endsWith(".class")) {
|
||||
isJar = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex);
|
||||
} finally {
|
||||
ZipFile.closeQuietly(zip);
|
||||
}
|
||||
return isJar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes settings used by the scanning functions of the archive
|
||||
* analyzer.
|
||||
*/
|
||||
private void initializeSettings() {
|
||||
maxScanDepth = getSettings().getInt("archive.scan.depth", 3);
|
||||
final String additionalZipExt = getSettings().getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
|
||||
if (additionalZipExt != null) {
|
||||
final String[] ext = additionalZipExt.split("\\s*,\\s*");
|
||||
Collections.addAll(KNOWN_ZIP_EXT, ext);
|
||||
}
|
||||
EXTENSIONS.addAll(KNOWN_ZIP_EXT);
|
||||
fileFilter = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* 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.io.FileFilter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
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;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
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;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.owasp.dependencycheck.dependency.EvidenceType;
|
||||
import org.owasp.dependencycheck.utils.XmlUtils;
|
||||
|
||||
/**
|
||||
* Analyzer for getting company, product, and version information from a .NET
|
||||
* assembly.
|
||||
*
|
||||
* @author colezlaw
|
||||
*
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* The analyzer name
|
||||
*/
|
||||
private static final String ANALYZER_NAME = "Assembly Analyzer";
|
||||
/**
|
||||
* The analysis phase
|
||||
*/
|
||||
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||
/**
|
||||
* The list of supported extensions
|
||||
*/
|
||||
private static final String[] SUPPORTED_EXTENSIONS = {"dll", "exe"};
|
||||
/**
|
||||
* The temp value for GrokAssembly.exe
|
||||
*/
|
||||
private File grokAssemblyExe = null;
|
||||
/**
|
||||
* The temp value for GrokAssembly.exe.config
|
||||
*/
|
||||
private File grokAssemblyConfig = null;
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class);
|
||||
|
||||
/**
|
||||
* Builds the beginnings of a List for ProcessBuilder
|
||||
*
|
||||
* @return the list of arguments to begin populating the ProcessBuilder
|
||||
*/
|
||||
protected List<String> buildArgumentList() {
|
||||
// Use file.separator as a wild guess as to whether this is Windows
|
||||
final List<String> args = new ArrayList<>();
|
||||
if (!SystemUtils.IS_OS_WINDOWS) {
|
||||
if (getSettings().getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
|
||||
args.add(getSettings().getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
|
||||
} else if (isInPath("mono")) {
|
||||
args.add("mono");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
args.add(grokAssemblyExe.getPath());
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the analysis on a single Dependency.
|
||||
*
|
||||
* @param dependency the dependency to analyze
|
||||
* @param engine the engine to perform the analysis under
|
||||
* @throws AnalysisException if anything goes sideways
|
||||
*/
|
||||
@Override
|
||||
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
final File test = new File(dependency.getActualFilePath());
|
||||
if (!test.isFile()) {
|
||||
throw new AnalysisException(String.format("%s does not exist and cannot be analyzed by dependency-check",
|
||||
dependency.getActualFilePath()));
|
||||
}
|
||||
if (grokAssemblyExe == null) {
|
||||
LOGGER.warn("GrokAssembly didn't get deployed");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
Document doc = null;
|
||||
try {
|
||||
final Process proc = pb.start();
|
||||
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) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
if (rc == 3) {
|
||||
LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check",
|
||||
dependency.getActualFilePath());
|
||||
return;
|
||||
} else if (rc != 0) {
|
||||
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 && !error.isEmpty()) {
|
||||
throw new AnalysisException(error);
|
||||
}
|
||||
|
||||
final String version = xpath.evaluate("/assembly/version", doc);
|
||||
if (version != null) {
|
||||
dependency.addEvidence(EvidenceType.VERSION, "grokassembly", "version", version, Confidence.HIGHEST);
|
||||
}
|
||||
|
||||
final String vendor = xpath.evaluate("/assembly/company", doc);
|
||||
if (vendor != null) {
|
||||
dependency.addEvidence(EvidenceType.VENDOR, "grokassembly", "vendor", vendor, Confidence.HIGH);
|
||||
}
|
||||
|
||||
final String product = xpath.evaluate("/assembly/product", doc);
|
||||
if (product != null) {
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, "grokassembly", "product", product, Confidence.HIGH);
|
||||
}
|
||||
|
||||
} catch (ParserConfigurationException pce) {
|
||||
throw new AnalysisException("Error initializing the assembly analyzer", pce);
|
||||
} catch (IOException | XPathExpressionException ioe) {
|
||||
throw new AnalysisException(ioe);
|
||||
} catch (SAXException saxe) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a
|
||||
* temporary location.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if anything goes wrong
|
||||
*/
|
||||
@Override
|
||||
public void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
|
||||
final File tempFile;
|
||||
final File cfgFile;
|
||||
try {
|
||||
tempFile = File.createTempFile("GKA", ".exe", getSettings().getTempDirectory());
|
||||
cfgFile = new File(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 = FileUtils.getResourceAsStream("GrokAssembly.exe");
|
||||
FileOutputStream fosCfg = new FileOutputStream(cfgFile);
|
||||
InputStream isCfg = FileUtils.getResourceAsStream("GrokAssembly.exe.config")) {
|
||||
IOUtils.copy(is, fos);
|
||||
grokAssemblyExe = tempFile;
|
||||
LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
|
||||
IOUtils.copy(isCfg, fosCfg);
|
||||
grokAssemblyConfig = cfgFile;
|
||||
LOGGER.debug("Extracted GrokAssembly.exe.config to {}", cfgFile);
|
||||
} catch (IOException ioe) {
|
||||
this.setEnabled(false);
|
||||
LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage());
|
||||
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();
|
||||
//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
|
||||
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 || 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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes resources used from the local file system.
|
||||
*
|
||||
* @throws Exception thrown if there is a problem closing the analyzer
|
||||
*/
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
try {
|
||||
if (grokAssemblyConfig != null && !grokAssemblyConfig.delete()) {
|
||||
LOGGER.debug("Unable to delete temporary GrokAssembly.exe.config; attempting delete on exit");
|
||||
grokAssemblyConfig.deleteOnExit();
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
LOGGER.debug("Can't delete temporary GrokAssembly.exe.config");
|
||||
grokAssemblyConfig.deleteOnExit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The File Filter used to filter supported extensions.
|
||||
*/
|
||||
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(
|
||||
SUPPORTED_EXTENSIONS).build();
|
||||
|
||||
@Override
|
||||
protected FileFilter getFileFilter() {
|
||||
return FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this analyzer's name.
|
||||
*
|
||||
* @return the analyzer name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return ANALYZER_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the phase this analyzer runs under.
|
||||
*
|
||||
* @return the phase this runs under
|
||||
*/
|
||||
@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_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;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ 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.owasp.dependencycheck.utils.UrlStringUtils;
|
||||
@@ -30,18 +29,22 @@ 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.dependency.EvidenceType;
|
||||
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();
|
||||
@@ -164,19 +168,14 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
final String contents = getFileContents(actualFile);
|
||||
if (!contents.isEmpty()) {
|
||||
if (isOutputScript) {
|
||||
extractConfigureScriptEvidence(dependency, name,
|
||||
contents);
|
||||
extractConfigureScriptEvidence(dependency, name, contents);
|
||||
} else {
|
||||
gatherEvidence(dependency, name, contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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.removeDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,17 +194,13 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
final String value = matcher.group(2);
|
||||
if (!value.isEmpty()) {
|
||||
if (variable.endsWith("NAME")) {
|
||||
dependency.getProductEvidence().addEvidence(name, variable,
|
||||
value, Confidence.HIGHEST);
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, name, variable, value, Confidence.HIGHEST);
|
||||
} else if ("VERSION".equals(variable)) {
|
||||
dependency.getVersionEvidence().addEvidence(name, variable,
|
||||
value, Confidence.HIGHEST);
|
||||
dependency.addEvidence(EvidenceType.VERSION, name, variable, value, Confidence.HIGHEST);
|
||||
} else if ("BUGREPORT".equals(variable)) {
|
||||
dependency.getVendorEvidence().addEvidence(name, variable,
|
||||
value, Confidence.HIGH);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, name, variable, value, Confidence.HIGH);
|
||||
} else if ("URL".equals(variable)) {
|
||||
dependency.getVendorEvidence().addEvidence(name, variable,
|
||||
value, Confidence.HIGH);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, name, variable, value, Confidence.HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,14 +215,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,27 +234,19 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
String contents) {
|
||||
final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
|
||||
if (matcher.find()) {
|
||||
final EvidenceCollection productEvidence = dependency
|
||||
.getProductEvidence();
|
||||
productEvidence.addEvidence(name, "Package", matcher.group(1),
|
||||
Confidence.HIGHEST);
|
||||
dependency.getVersionEvidence().addEvidence(name,
|
||||
"Package Version", matcher.group(2), Confidence.HIGHEST);
|
||||
final EvidenceCollection vendorEvidence = dependency
|
||||
.getVendorEvidence();
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, name, "Package", matcher.group(1), Confidence.HIGHEST);
|
||||
dependency.addEvidence(EvidenceType.VERSION, name, "Package Version", matcher.group(2), Confidence.HIGHEST);
|
||||
|
||||
if (null != matcher.group(3)) {
|
||||
vendorEvidence.addEvidence(name, "Bug report address",
|
||||
matcher.group(4), Confidence.HIGH);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, name, "Bug report address", matcher.group(4), Confidence.HIGH);
|
||||
}
|
||||
if (null != matcher.group(5)) {
|
||||
productEvidence.addEvidence(name, "Tarname", matcher.group(6),
|
||||
Confidence.HIGH);
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, name, "Tarname", matcher.group(6), Confidence.HIGH);
|
||||
}
|
||||
if (null != matcher.group(7)) {
|
||||
final String url = matcher.group(8);
|
||||
if (UrlStringUtils.isUrl(url)) {
|
||||
vendorEvidence.addEvidence(name, "URL", url,
|
||||
Confidence.HIGH);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, name, "URL", url, Confidence.HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,10 +255,12 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
/**
|
||||
* Initializes the file type analyzer.
|
||||
*
|
||||
* @throws Exception thrown if there is an exception during initialization
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if there is an exception during
|
||||
* initialization
|
||||
*/
|
||||
@Override
|
||||
protected void initializeFileTypeAnalyzer() throws Exception {
|
||||
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
|
||||
// No initialization needed.
|
||||
}
|
||||
}
|
||||
@@ -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,25 +32,35 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.owasp.dependencycheck.dependency.EvidenceType;
|
||||
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 {
|
||||
|
||||
/**
|
||||
* A descriptor for the type of dependencies processed or added by this
|
||||
* analyzer.
|
||||
*/
|
||||
public static final String DEPENDENCY_ECOSYSTEM = "CMAKE";
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
@@ -59,18 +69,23 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
/**
|
||||
* Used when compiling file scanning regex patterns.
|
||||
*/
|
||||
private static final int REGEX_OPTIONS = Pattern.DOTALL
|
||||
| Pattern.CASE_INSENSITIVE | Pattern.MULTILINE;
|
||||
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
|
||||
private static final Pattern SET_VERSION = Pattern
|
||||
.compile(
|
||||
"^ *set\\s*\\(\\s*(\\w+)_version\\s+\"?(\\d+(?:\\.\\d+)+)[\\s\"]?\\)",
|
||||
REGEX_OPTIONS);
|
||||
/**
|
||||
* 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\"]?\\)", REGEX_OPTIONS);
|
||||
|
||||
/**
|
||||
* Detects files that can be analyzed.
|
||||
@@ -78,24 +93,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 +124,15 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op initializer implementation.
|
||||
* Initializes the analyzer.
|
||||
*
|
||||
* @throws Exception never thrown
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if an exception occurs getting an
|
||||
* instance of SHA1
|
||||
*/
|
||||
@Override
|
||||
protected void initializeFileTypeAnalyzer() throws Exception {
|
||||
// Nothing to do here.
|
||||
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,23 +140,21 @@ 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)
|
||||
throws AnalysisException {
|
||||
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
dependency.setEcosystem(DEPENDENCY_ECOSYSTEM);
|
||||
final File file = dependency.getActualFile();
|
||||
final String parentName = file.getParentFile().getName();
|
||||
final String name = file.getName();
|
||||
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);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(contents)) {
|
||||
final Matcher m = PROJECT.matcher(contents);
|
||||
int count = 0;
|
||||
@@ -163,50 +164,61 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
"Found project command match with %d groups: %s",
|
||||
m.groupCount(), m.group(0)));
|
||||
final String group = m.group(1);
|
||||
LOGGER.debug("Group 1: " + group);
|
||||
dependency.getProductEvidence().addEvidence(name, "Project",
|
||||
group, Confidence.HIGH);
|
||||
LOGGER.debug("Group 1: {}", group);
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, name, "Project", group, Confidence.HIGH);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, name, "Project", group, Confidence.HIGH);
|
||||
dependency.setName(group);
|
||||
}
|
||||
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
|
||||
*/
|
||||
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);
|
||||
LOGGER.debug("Group 2: " + version);
|
||||
LOGGER.debug("Group 1: {}", product);
|
||||
LOGGER.debug("Group 2: {}", version);
|
||||
final String aliasPrefix = "ALIASOF_";
|
||||
if (product.startsWith(aliasPrefix)) {
|
||||
product = product.replaceFirst(aliasPrefix, "");
|
||||
}
|
||||
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.setEcosystem(DEPENDENCY_ECOSYSTEM);
|
||||
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);
|
||||
currentDep.setSha1sum(Checksum.getSHA1Checksum(filePath));
|
||||
currentDep.setMd5sum(Checksum.getMD5Checksum(filePath));
|
||||
engine.addDependency(currentDep);
|
||||
}
|
||||
final String source = dependency.getDisplayFileName();
|
||||
dependency.getProductEvidence().addEvidence(source, "Product",
|
||||
product, Confidence.MEDIUM);
|
||||
dependency.getVersionEvidence().addEvidence(source, "Version",
|
||||
version, Confidence.MEDIUM);
|
||||
final String source = currentDep.getFileName();
|
||||
currentDep.addEvidence(EvidenceType.PRODUCT, source, "Product", product, Confidence.MEDIUM);
|
||||
currentDep.addEvidence(EvidenceType.VENDOR, source, "Vendor", product, Confidence.MEDIUM);
|
||||
currentDep.addEvidence(EvidenceType.VERSION, source, "Version", version, Confidence.MEDIUM);
|
||||
currentDep.setName(product);
|
||||
currentDep.setVersion(version);
|
||||
}
|
||||
LOGGER.debug(String.format("Found %d matches.", count));
|
||||
LOGGER.debug("Found {} matches.", count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -21,10 +21,15 @@ import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.lucene.analysis.util.CharArraySet;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.queryparser.classic.ParseException;
|
||||
@@ -37,26 +42,31 @@ import org.owasp.dependencycheck.data.cpe.Fields;
|
||||
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
||||
import org.owasp.dependencycheck.data.cpe.IndexException;
|
||||
import org.owasp.dependencycheck.data.lucene.LuceneUtils;
|
||||
import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer;
|
||||
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.Evidence;
|
||||
import org.owasp.dependencycheck.dependency.EvidenceCollection;
|
||||
import org.owasp.dependencycheck.dependency.EvidenceType;
|
||||
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 {
|
||||
@ThreadSafe
|
||||
public class CPEAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
/**
|
||||
* The Logger.
|
||||
@@ -65,23 +75,32 @@ 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. Note, the :/ are included so URLs are
|
||||
* passed into the Lucene query so that the specialized tokenizer can parse
|
||||
* them.
|
||||
*/
|
||||
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 URL to perform a search of the NVD CVE data at NIST.
|
||||
*/
|
||||
public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
|
||||
/**
|
||||
* The CPE in memory index.
|
||||
*/
|
||||
@@ -90,11 +109,12 @@ public class CPEAnalyzer implements Analyzer {
|
||||
* The CVE Database.
|
||||
*/
|
||||
private CveDB cve;
|
||||
|
||||
/**
|
||||
* The URL to perform a search of the NVD CVE data at NIST.
|
||||
* The list of ecosystems to skip during analysis. These are skipped because
|
||||
* there is generally a more accurate vulnerability analyzer in the
|
||||
* pipeline.
|
||||
*/
|
||||
public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
|
||||
private List<String> skipEcosystems;
|
||||
|
||||
/**
|
||||
* Returns the name of this analyzer.
|
||||
@@ -119,28 +139,48 @@ public class CPEAnalyzer implements Analyzer {
|
||||
/**
|
||||
* Creates the CPE Lucene Index.
|
||||
*
|
||||
* @throws Exception is thrown if there is an issue opening the index.
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException is thrown if there is an issue opening
|
||||
* the index.
|
||||
*/
|
||||
@Override
|
||||
public void initialize() throws Exception {
|
||||
this.open();
|
||||
public void prepareAnalyzer(Engine engine) throws InitializationException {
|
||||
super.prepareAnalyzer(engine);
|
||||
try {
|
||||
this.open(engine.getDatabase());
|
||||
} 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);
|
||||
}
|
||||
final String[] tmp = engine.getSettings().getArray(Settings.KEYS.ECOSYSTEM_SKIP_CPEANALYZER);
|
||||
if (tmp == null) {
|
||||
skipEcosystems = new ArrayList<>();
|
||||
} else {
|
||||
LOGGER.info("Skipping CPE Analysis for {}", tmp);
|
||||
skipEcosystems = Arrays.asList(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param cve a reference to the NVD CVE database
|
||||
* @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();
|
||||
public void open(CveDB cve) throws IOException, DatabaseException {
|
||||
this.cve = cve;
|
||||
this.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 +191,17 @@ public class CPEAnalyzer implements Analyzer {
|
||||
* Closes the data sources.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
public void closeAnalyzer() {
|
||||
if (cpe != null) {
|
||||
cpe.close();
|
||||
cpe = null;
|
||||
}
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
cve = null;
|
||||
}
|
||||
}
|
||||
|
||||
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,21 +209,20 @@ 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
|
||||
String vendors = "";
|
||||
String products = "";
|
||||
for (Confidence confidence : Confidence.values()) {
|
||||
if (dependency.getVendorEvidence().contains(confidence)) {
|
||||
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
|
||||
if (dependency.contains(EvidenceType.VENDOR, confidence)) {
|
||||
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getIterator(EvidenceType.VENDOR, confidence));
|
||||
LOGGER.debug("vendor search: {}", vendors);
|
||||
}
|
||||
if (dependency.getProductEvidence().contains(confidence)) {
|
||||
products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence);
|
||||
if (dependency.contains(EvidenceType.PRODUCT, confidence)) {
|
||||
products = addEvidenceWithoutDuplicateTerms(products, dependency.getIterator(EvidenceType.PRODUCT, confidence));
|
||||
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.getVendorWeightings(),
|
||||
dependency.getProductWeightings());
|
||||
if (entries == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -212,29 +244,31 @@ 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.
|
||||
* <p>
|
||||
* 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.</p>
|
||||
* <p>
|
||||
* Note, if the evidence is longer then 200 characters it will be
|
||||
* truncated.</p>
|
||||
*
|
||||
* @param text the base text.
|
||||
* @param ec an EvidenceCollection
|
||||
* @param confidenceFilter a Confidence level to filter the evidence by.
|
||||
* @param text the base text
|
||||
* @param evidence an iterable set of evidence to concatenate
|
||||
* @return the new evidence text
|
||||
*/
|
||||
private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) {
|
||||
@SuppressWarnings("null")
|
||||
protected String addEvidenceWithoutDuplicateTerms(final String text, final Iterable<Evidence> evidence) {
|
||||
final String txt = (text == null) ? "" : text;
|
||||
final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
|
||||
final StringBuilder sb = new StringBuilder(txt.length() * 2);
|
||||
sb.append(' ').append(txt).append(' ');
|
||||
for (Evidence e : ec.iterator(confidenceFilter)) {
|
||||
for (Evidence e : evidence) {
|
||||
String value = e.getValue();
|
||||
|
||||
//hack to get around the fact that lucene does a really good job of recognizing domains and not
|
||||
// splitting them. TODO - put together a better lucene analyzer specific to the domain.
|
||||
if (value.startsWith("http://")) {
|
||||
value = value.substring(7).replaceAll("\\.", " ");
|
||||
}
|
||||
if (value.startsWith("https://")) {
|
||||
value = value.substring(8).replaceAll("\\.", " ");
|
||||
if (value.length() > 1000) {
|
||||
value = value.substring(0, 1000);
|
||||
final int pos = value.lastIndexOf(" ");
|
||||
if (pos > 0) {
|
||||
value = value.substring(0, pos);
|
||||
}
|
||||
}
|
||||
if (sb.indexOf(" " + value + " ") < 0) {
|
||||
sb.append(value).append(' ');
|
||||
@@ -245,23 +279,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 +319,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 +330,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,52 +364,71 @@ 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(field).append(":(");
|
||||
|
||||
final String cleanText = cleanseText(searchText);
|
||||
|
||||
if ("".equals(cleanText)) {
|
||||
if (cleanText.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (weightedText == null || weightedText.isEmpty()) {
|
||||
LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
|
||||
} else {
|
||||
boolean addSpace = false;
|
||||
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;
|
||||
if (temp.length() > 0) {
|
||||
temp.append(' ');
|
||||
}
|
||||
LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr);
|
||||
temp.append(WEIGHTING_BOOST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (temp == null) {
|
||||
temp = LuceneUtils.escapeLuceneQuery(word);
|
||||
if (addSpace) {
|
||||
sb.append(' ');
|
||||
} else {
|
||||
addSpace = true;
|
||||
}
|
||||
if (temp == null) {
|
||||
LuceneUtils.appendEscapedLuceneQuery(sb, word);
|
||||
} else {
|
||||
sb.append(temp);
|
||||
}
|
||||
sb.append(" ").append(temp);
|
||||
}
|
||||
}
|
||||
sb.append(" ) ");
|
||||
sb.append(")");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 +438,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 +456,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.
|
||||
@@ -408,8 +469,8 @@ public class CPEAnalyzer implements Analyzer {
|
||||
|
||||
//TODO - does this nullify some of the fuzzy matching that happens in the lucene search?
|
||||
// for instance CPE some-component and in the evidence we have SomeComponent.
|
||||
if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct())
|
||||
&& collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) {
|
||||
if (collectionContainsString(dependency.getEvidence(EvidenceType.PRODUCT), entry.getProduct())
|
||||
&& collectionContainsString(dependency.getEvidence(EvidenceType.VENDOR), entry.getVendor())) {
|
||||
//&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion())
|
||||
isValid = true;
|
||||
}
|
||||
@@ -419,19 +480,23 @@ public class CPEAnalyzer implements Analyzer {
|
||||
/**
|
||||
* Used to determine if the EvidenceCollection contains a specific string.
|
||||
*
|
||||
* @param ec an EvidenceCollection
|
||||
* @param evidence an of evidence object to check
|
||||
* @param text the text to search for
|
||||
* @return whether or not the EvidenceCollection contains the string
|
||||
*/
|
||||
private boolean collectionContainsString(EvidenceCollection ec, String text) {
|
||||
private boolean collectionContainsString(Set<Evidence> evidence, String text) {
|
||||
//TODO - likely need to change the split... not sure if this will work for CPE with special chars
|
||||
if (text == null) {
|
||||
return false;
|
||||
}
|
||||
final String[] words = text.split("[\\s_-]");
|
||||
final List<String> list = new ArrayList<String>();
|
||||
final List<String> list = new ArrayList<>();
|
||||
String tempWord = null;
|
||||
final CharArraySet stopWords = SearchFieldAnalyzer.getStopWords();
|
||||
for (String word : words) {
|
||||
if (stopWords.contains(word)) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
single letter words should be concatenated with the next word.
|
||||
so { "m", "core", "sample" } -> { "mcore", "sample" }
|
||||
@@ -456,22 +521,40 @@ public class CPEAnalyzer implements Analyzer {
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
boolean contains = true;
|
||||
boolean isValid = true;
|
||||
for (String word : list) {
|
||||
contains &= ec.containsUsedString(word);
|
||||
boolean found = false;
|
||||
for (Evidence e : evidence) {
|
||||
if (e.getValue().toLowerCase().contains(word.toLowerCase())) {
|
||||
if ("http".equals(word) && e.getValue().contains("http:")) {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
isValid &= found;
|
||||
if (!isValid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return contains;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
if (skipEcosystems.contains(dependency.getEcosystem())) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
determineCPE(dependency);
|
||||
} catch (CorruptIndexException ex) {
|
||||
@@ -484,29 +567,37 @@ 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,
|
||||
Confidence currentConfidence) throws UnsupportedEncodingException {
|
||||
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
|
||||
if (cpes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
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)) {
|
||||
for (Evidence evidence : dependency.getIterator(EvidenceType.VERSION, conf)) {
|
||||
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
|
||||
if (evVer == null) {
|
||||
continue;
|
||||
@@ -514,7 +605,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 +618,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 +643,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 +671,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 +697,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 +758,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 +776,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 +843,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,12 @@ 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 javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.dependency.EvidenceType;
|
||||
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,11 +46,12 @@ 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
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
@@ -70,43 +75,43 @@ 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.
|
||||
* There may be temporary issues when connecting to MavenCentral. In order
|
||||
* to compensate for 99% of the issues, we perform a retry before finally
|
||||
* failing the analysis.
|
||||
*/
|
||||
private boolean errorFlag = false;
|
||||
private static final int NUMBER_OF_TRIES = 5;
|
||||
|
||||
/**
|
||||
* The searcher itself.
|
||||
*/
|
||||
private CentralSearch searcher;
|
||||
/**
|
||||
* Field indicating if the analyzer is enabled.
|
||||
*/
|
||||
private final boolean enabled = checkEnabled();
|
||||
|
||||
/**
|
||||
* Determine whether to enable this analyzer or not.
|
||||
* Initializes the analyzer with the configured settings.
|
||||
*
|
||||
* @return whether the analyzer should be enabled
|
||||
* @param settings the configured settings to use
|
||||
*/
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
public void initialize(Settings settings) {
|
||||
super.initialize(settings);
|
||||
setEnabled(checkEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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))) {
|
||||
if (getSettings().getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
|
||||
if (!getSettings().getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
|
||||
|| NexusAnalyzer.DEFAULT_URL.equals(getSettings().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 +121,26 @@ 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
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException if there's an error during initialization
|
||||
*/
|
||||
@Override
|
||||
public void initializeFileTypeAnalyzer() throws Exception {
|
||||
public void prepareFileTypeAnalyzer(Engine engine) 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(getSettings());
|
||||
} catch (MalformedURLException ex) {
|
||||
setEnabled(false);
|
||||
throw new InitializationException("The configured URL to Maven Central is malformed", 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,19 +193,15 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* @throws AnalysisException when there's an exception during analysis
|
||||
*/
|
||||
@Override
|
||||
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
if (errorFlag || !isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
|
||||
try {
|
||||
final List<MavenArtifact> mas = searcher.searchSha1(dependency.getSha1sum());
|
||||
final List<MavenArtifact> mas = fetchMavenArtifacts(dependency);
|
||||
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()) {
|
||||
for (Evidence e : dependency.getEvidence(EvidenceType.VENDOR)) {
|
||||
if ("pom".equals(e.getSource())) {
|
||||
pomAnalyzed = true;
|
||||
break;
|
||||
@@ -204,7 +210,7 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
if (!pomAnalyzed && ma.getPomUrl() != null) {
|
||||
File pomFile = null;
|
||||
try {
|
||||
final File baseDir = Settings.getTempDirectory();
|
||||
final File baseDir = getSettings().getTempDirectory();
|
||||
pomFile = File.createTempFile("pom", ".xml", baseDir);
|
||||
if (!pomFile.delete()) {
|
||||
LOGGER.warn("Unable to fetch pom.xml for {} from Central; "
|
||||
@@ -212,14 +218,16 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
LOGGER.debug("Unable to delete temp file");
|
||||
}
|
||||
LOGGER.debug("Downloading {}", ma.getPomUrl());
|
||||
Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
|
||||
final Downloader downloader = new Downloader(getSettings());
|
||||
downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
|
||||
PomUtils.analyzePOM(dependency, pomFile);
|
||||
|
||||
} catch (DownloadFailedException ex) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -231,8 +239,61 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName());
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.debug("Could not connect to Central search", ioe);
|
||||
errorFlag = true;
|
||||
final String message = "Could not connect to Central search. Analysis failed.";
|
||||
LOGGER.error(message, ioe);
|
||||
throw new AnalysisException(message, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the corresponding list of MavenArtifacts of the given
|
||||
* dependency from MavenCentral.
|
||||
* <p>
|
||||
* As the connection to MavenCentral is known to be unreliable, we implement
|
||||
* a simple retry logic in order to compensate for 99% of the issues.
|
||||
*
|
||||
* @param dependency the dependency to analyze
|
||||
* @return the downloaded list of MavenArtifacts
|
||||
* @throws FileNotFoundException if the specified artifact is not found
|
||||
* @throws IOException if connecting to MavenCentral finally failed
|
||||
*/
|
||||
protected List<MavenArtifact> fetchMavenArtifacts(Dependency dependency) throws IOException {
|
||||
IOException lastException = null;
|
||||
long sleepingTimeBetweenRetriesInMillis = 1000;
|
||||
int triesLeft = NUMBER_OF_TRIES;
|
||||
while (triesLeft-- > 0) {
|
||||
try {
|
||||
return searcher.searchSha1(dependency.getSha1sum());
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// retry does not make sense, just throw the exception
|
||||
throw fnfe;
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.debug("Could not connect to Central search (tries left: {}): {}",
|
||||
triesLeft, ioe.getMessage());
|
||||
lastException = ioe;
|
||||
|
||||
if (triesLeft > 0) {
|
||||
try {
|
||||
Thread.sleep(sleepingTimeBetweenRetriesInMillis);
|
||||
sleepingTimeBetweenRetriesInMillis *= 2;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String message = "Finally failed connecting to Central search."
|
||||
+ " Giving up after " + NUMBER_OF_TRIES + " tries.";
|
||||
throw new IOException(message, lastException);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used by unit tests to setup the analyzer.
|
||||
*
|
||||
* @param searcher the Central Search object to use.
|
||||
*/
|
||||
protected void setCentralSearch(CentralSearch searcher) {
|
||||
this.searcher = searcher;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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 javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
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.EvidenceType;
|
||||
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
|
||||
@ThreadSafe
|
||||
public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* A descriptor for the type of dependencies processed or added by this
|
||||
* analyzer.
|
||||
*/
|
||||
public static final String DEPENDENCY_ECOSYSTEM = "CocoaPod";
|
||||
|
||||
/**
|
||||
* 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 prepareFileTypeAnalyzer(Engine engine) {
|
||||
// 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 {
|
||||
|
||||
dependency.setEcosystem(DEPENDENCY_ECOSYSTEM);
|
||||
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 String name = determineEvidence(contents, blockVariable, "name");
|
||||
if (!name.isEmpty()) {
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, PODSPEC, "name_project", name, Confidence.HIGHEST);
|
||||
dependency.addEvidence(EvidenceType.VENDOR, PODSPEC, "name_project", name, Confidence.HIGHEST);
|
||||
dependency.setName(name);
|
||||
}
|
||||
final String summary = determineEvidence(contents, blockVariable, "summary");
|
||||
if (!summary.isEmpty()) {
|
||||
dependency.addEvidence(EvidenceType.PRODUCT, PODSPEC, "summary", summary, Confidence.HIGHEST);
|
||||
}
|
||||
|
||||
final String author = determineEvidence(contents, blockVariable, "authors?");
|
||||
if (!author.isEmpty()) {
|
||||
dependency.addEvidence(EvidenceType.VENDOR, PODSPEC, "author", author, Confidence.HIGHEST);
|
||||
}
|
||||
final String homepage = determineEvidence(contents, blockVariable, "homepage");
|
||||
if (!homepage.isEmpty()) {
|
||||
dependency.addEvidence(EvidenceType.VENDOR, PODSPEC, "homepage", homepage, Confidence.HIGHEST);
|
||||
}
|
||||
final String license = determineEvidence(contents, blockVariable, "licen[cs]es?");
|
||||
if (!license.isEmpty()) {
|
||||
dependency.setLicense(license);
|
||||
}
|
||||
|
||||
final String version = determineEvidence(contents, blockVariable, "version");
|
||||
if (!version.isEmpty()) {
|
||||
dependency.addEvidence(EvidenceType.VERSION, PODSPEC, "version", version, Confidence.HIGHEST);
|
||||
dependency.setVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
setPackagePath(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts evidence from the contents and adds it to the given evidence
|
||||
* collection.
|
||||
*
|
||||
* @param contents the text to extract evidence from
|
||||
* @param blockVariable the block variable within the content to search for
|
||||
* @param fieldPattern the field pattern within the contents to search for
|
||||
* @return the evidence
|
||||
*/
|
||||
private String determineEvidence(String contents, String blockVariable, String fieldPattern) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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 org.owasp.dependencycheck.dependency.EvidenceType;
|
||||
|
||||
/**
|
||||
* Used to analyze a composer.lock file for a composer PHP app.
|
||||
*
|
||||
* @author colezlaw
|
||||
*/
|
||||
@Experimental
|
||||
public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* A descriptor for the type of dependencies processed or added by this
|
||||
* analyzer.
|
||||
*/
|
||||
public static final String DEPENDENCY_ECOSYSTEM = "Composer";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param engine a reference to the dependency-check engine
|
||||
* @throws InitializationException thrown if an exception occurs getting an
|
||||
* instance of SHA1
|
||||
*/
|
||||
@Override
|
||||
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.debug("Checking composer.lock file {}", dependency.getActualFilePath());
|
||||
clp.process();
|
||||
//if dependencies are found in the lock, then there is always an empty shell dependency left behind for the
|
||||
//composer.lock. The first pass through, reuse the top level dependency, and add new ones for the rest.
|
||||
boolean processedAtLeastOneDep = false;
|
||||
for (ComposerDependency dep : clp.getDependencies()) {
|
||||
final Dependency d = new Dependency(dependency.getActualFile());
|
||||
final String filePath = String.format("%s:%s/%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject(), dep.getVersion());
|
||||
d.setName(dep.getProject());
|
||||
d.setVersion(dep.getVersion());
|
||||
d.setEcosystem(DEPENDENCY_ECOSYSTEM);
|
||||
d.setFilePath(filePath);
|
||||
d.setSha1sum(Checksum.getSHA1Checksum(filePath));
|
||||
d.setMd5sum(Checksum.getMD5Checksum(filePath));
|
||||
d.addEvidence(EvidenceType.VENDOR, COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST);
|
||||
d.addEvidence(EvidenceType.PRODUCT, COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
|
||||
d.addEvidence(EvidenceType.VERSION, COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
|
||||
LOGGER.debug("Adding dependency {}", d.getDisplayFileName());
|
||||
engine.addDependency(d);
|
||||
//make sure we only remove the main dependency if we went through this loop at least once.
|
||||
processedAtLeastOneDep = true;
|
||||
}
|
||||
// remove the dependency at the end because it's referenced in the loop itself.
|
||||
// double check the name to be sure we only remove the generic entry.
|
||||
if (processedAtLeastOneDep && dependency.getDisplayFileName().equalsIgnoreCase("composer.lock")) {
|
||||
LOGGER.debug("Removing main redundant dependency {}", dependency.getDisplayFileName());
|
||||
engine.removeDependency(dependency);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@@ -17,20 +17,19 @@
|
||||
*/
|
||||
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 javax.annotation.concurrent.ThreadSafe;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* The suppression analyzer processes an externally defined XML document that complies with the suppressions.xsd schema.
|
||||
* Any identified CPE 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 CPE entries within
|
||||
* the dependencies that match will be removed.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
|
||||
/**
|
||||
* The name of the analyzer.
|
||||
*/
|
||||
@@ -59,17 +58,15 @@ public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
|
||||
public AnalysisPhase getAnalysisPhase() {
|
||||
return ANALYSIS_PHASE;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns the setting key to determine if the analyzer is enabled.</p>
|
||||
*
|
||||
* @return the key for the analyzer's enabled property
|
||||
*/
|
||||
@Override
|
||||
public void analyze(final Dependency dependency, final Engine engine) throws AnalysisException {
|
||||
|
||||
if (getRules() == null || getRules().size() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final SuppressionRule rule : getRules()) {
|
||||
rule.process(dependency);
|
||||
}
|
||||
protected String getAnalyzerEnabledSettingKey() {
|
||||
return Settings.KEYS.ANALYZER_CPE_SUPPRESSION_ENABLED;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user