├── .env ├── .gitignore ├── .travis.yml ├── CHANGES.rst ├── LICENSE ├── MANIFEST.in ├── README.rst ├── dependency_check.gif ├── dependency_check.py ├── dev-requirements.txt ├── requirements.txt ├── setup.cfg ├── setup.py ├── tasks.py └── tests ├── conftest.py └── test_cli.py /.env: -------------------------------------------------------------------------------- 1 | # /bin/bash - help gedit syntax highlight do the right thing 2 | # autoenv script (https://github.com/kennethreitz/autoenv) 3 | # Use ". .env -h" for help. 4 | # 5 | # This script is an autoenev script that either activates or creates 6 | # a local virtualenv in '.venv' for (almost) any project. Typical 7 | # project assets like 'setup.py' and requirements files are used to 8 | # populate the virtualenv. 9 | # 10 | # This script is tested with bash, report problems with other shells to 11 | # 12 | # https://github.com/Springerle/py-generic-project/issues 13 | # 14 | # It should work on any Linux, and Mac OSX. 15 | # 16 | _venv_virtualenv="/usr/bin/python3 -m venv" 17 | _venv_py3=true 18 | _venv_choices=('$_venv_py_tk' 3.9 3.8 3.7 3.6 3.5 3) 19 | _venv_pip_req='pip>20' 20 | _venv_bin=bin 21 | _venv_master_url="https://raw.githubusercontent.com/Springerle/py-generic-project/master/.env" 22 | : ${USER:=$USERNAME} 23 | 24 | #_venv_temp=/usr/local/bin/virtualenv 25 | #if test -x $_venv_temp; then 26 | # _venv_virtualenv=$_venv_temp 27 | #fi 28 | test "${_venv_py3:0:2}" != '{''{' || _venv_py3=true 29 | if test -n "$SYSTEMROOT" -a -n "$WINDIR"; then 30 | _venv_virtualenv=$(cygpath -au "$(py -3 -c 'import sys; print(sys.executable)')")" -m venv" 31 | _venv_bin=Scripts 32 | elif $_venv_py3; then # Python 3 mode? 33 | # /opt/pyenv, see https://github.com/jhermann/priscilla/tree/master/pyenv 34 | _venv_temp=/opt/pyenv/bin/python3 35 | if test -x $_venv_temp; then 36 | _venv_virtualenv="$_venv_temp -m venv" 37 | fi 38 | # python3 venv in recent Debian / Ubuntu 39 | # prefer a version that has Tkinter installed, if available 40 | _venv_py_tk=$(dpkg-query -W -f '${Version}\n' 'python3*-tk' 2>/dev/null | sort -rV | head -n1 | cut -f-2 -d.) 41 | for _venv_temp in "${_venv_choices[@]}"; do 42 | _venv_temp="/usr/bin/python$(eval echo $_venv_temp)" 43 | if test -x $_venv_temp; then 44 | _venv_virtualenv="$_venv_temp -m venv" 45 | break 46 | fi 47 | done 48 | unset _venv_py_tk 49 | fi 50 | 51 | _venv_readlink=readlink 52 | case "$(uname -s)" in 53 | # See http://en.wikipedia.org/wiki/Uname#Examples 54 | Darwin) 55 | _venv_temp="/usr/local/opt/coreutils/libexec/gnubin/readlink" 56 | if test -x $_venv_temp; then 57 | _venv_readlink=$_venv_temp 58 | else 59 | echo "*** No readlink command, do a 'brew install coreutils'..." 60 | return 1 61 | fi 62 | ;; 63 | CYGWIN*) 64 | ;; 65 | Linux|*) 66 | ;; 67 | esac 68 | 69 | test -z "$JENKINS_URL" || echo '***' "\$0=$0" "\$BASH_SOURCE=${BASH_SOURCE[0]}" 70 | if test "$0" = "-bash" -o "$(basename -- "$0")" = "bash" -o "$(basename -- "${BASH_SOURCE[0]}")" = ".env"; then 71 | _venv_script=$($_venv_readlink -f ${BASH_SOURCE[0]}) 72 | elif test "$(basename -- "$0")" = ".env"; then 73 | _venv_script=$($_venv_readlink -f "$0") 74 | fi 75 | _venv_script="${_venv_script:-/dont-know-really/.env}" 76 | _venv_xtrace=$(set +o | grep xtrace) 77 | set +x 78 | _venv_name="$(basename $(pwd))" 79 | 80 | _venv_pip_log() { 81 | if $_venv_verbose; then 82 | cat 83 | else 84 | egrep "Found.existing.installation|Collecting|Installing.collected.packages|Searching.for|Installed|Finished" 85 | fi 86 | } 87 | 88 | # command line flags, mostly for CI server usage 89 | _venv_create=false 90 | _venv_develop=false 91 | _venv_verbose=false 92 | while test "${1:0:1}" = "-"; do 93 | case "$1" in 94 | --yes) _venv_create=true ;; 95 | --develop) _venv_develop=true ;; 96 | --verbose | -v) _venv_verbose=true; set -x ;; 97 | --virtualenv) shift; _venv_virtualenv="$1" ;; 98 | --help | -h) 99 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 100 | echo "usage: . $_venv_script " 101 | echo 102 | echo "Create and/or activate a Python virtual environment. Updates pip and other" 103 | echo "system packages, and recognizes 'dev-requirements.txt' and 'setup.py' or" 104 | echo "'requirements.txt'." 105 | echo 106 | echo "This is an autoenv script (see https://github.com/kennethreitz/autoenv)." 107 | echo 108 | echo "Options:" 109 | echo " --yes create missing venv without prompting" 110 | echo " --develop call 'develop -U' on activation" 111 | echo " -v | --verbose don't filter install logs on terminal" 112 | echo " (full logs in '.venv/install-*.log')" 113 | echo " -h | --help this help message" 114 | echo " --virtualenv PATH set explicit path of virtualenv binary to use" 115 | echo " --update update to the newest master copy" 116 | return 1 117 | ;; 118 | --update) 119 | ( cd /tmp && $(command which python3 py 2>/dev/null | head -n1) </dev/null || return 1 129 | sed -r -e "s/^_venv_py3=.*/_venv_py3=$_venv_py3/" <"/tmp/$USER-py-env-update.py" >.env 130 | git diff .env || : 131 | echo ".env script update OK" 132 | return 0 133 | ;; 134 | *) echo "WARNING: Ignored unknown option '$1'" ;; 135 | esac 136 | shift 137 | done 138 | 139 | # Outside the tree of the .env script? 140 | if pwd -P | egrep -v '^'$(dirname "$_venv_script")'($|/)' >/dev/null; then 141 | : echo Outside "[$0 $1 ; $_venv_script]" 142 | 143 | # Inside the tree of the .env script, but have another local '.env'? 144 | elif test \! -f .env -o "$_venv_script" != "$(pwd -P)/.env"; then 145 | : echo Inside "[$0 $1 ; $_venv_script]" 146 | 147 | # Only try virtualenv creation outside of template dirs; the egrep pattern is escaped for hiding it from Jinja2 148 | elif pwd -P | egrep -v '/{''{''.*''}''}(/|$)' >/dev/null || $_venv_create; then 149 | test -f ".env" && _venv_ask=true || _venv_ask=false 150 | 151 | # Look for existing venv at common locations 152 | for _venv_base in .venv/$_venv_name .venv venv/$_venv_name venv . ..; do 153 | if test -f "$_venv_base/$_venv_bin/activate"; then 154 | deactivate 2>/dev/null || : 155 | . "$_venv_base/$_venv_bin/activate" 156 | if test -f setup.py; then 157 | $_venv_develop && $_venv_base/$_venv_bin/python setup.py -q develop -U || : 158 | $_venv_base/$_venv_bin/python setup.py --name --version --url | tr -d \\r \ 159 | | xargs -d$'\n' printf "*** Activated %s %s @ %s\\n" || : 160 | else 161 | echo "*** Activated $_venv_base" 162 | fi 163 | _venv_ask=false 164 | break 165 | fi 166 | done 167 | 168 | if $_venv_ask && test \! -d .venv; then 169 | $_venv_create || { read -p "No virtualenv found, shall I create one for you? [Y/n] " -n 1 -r || REPLY='n'; echo; } 170 | if $_venv_create || echo "$REPLY" | egrep '^[Yy]?$' >/dev/null; then 171 | # Create, activate, and update virtualenv 172 | echo "Calling: $_venv_virtualenv --prompt $_venv_name .venv/" 173 | eval $_venv_virtualenv "--prompt $_venv_name .venv/" 174 | . ".venv/$_venv_bin/activate" 175 | ".venv/$_venv_bin/python" -m pip --log ".venv/install-pip.log" install -U "$_venv_pip_req" 2>&1 | _venv_pip_log \ 176 | || echo >&2 "!!! WARN: pip -U pip failed (RC=$?), see .venv/install-pip.log for details" 177 | ".venv/$_venv_bin/python" -m pip --log ".venv/install-tools.log" install -U "setuptools>40" "wheel>0.30" 2>&1 | _venv_pip_log \ 178 | || echo >&2 "!!! WARN: pip -U setuptools wheel failed (RC=$?), see .venv/install-tools.log for details" 179 | 180 | # Get rid of cruft some older systems produce 181 | ".venv/$_venv_bin/python" -m pip --log ".venv/uninstall-distribute.log" uninstall --yes distribute >/dev/null 2>&1 || : 182 | 183 | # pypandoc fails when the base package is missing, so we install it here, if possible 184 | if which pandoc >/dev/null 2>&1 ; then 185 | ".venv/$_venv_bin/python" -m pip --log ".venv/install-pandoc.log" install pypandoc 2>&1 | _venv_pip_log \ 186 | || echo >&2 "!!! WARN: pip install pypandoc failed (RC=$?), see .venv/install-pandoc.log for details" 187 | fi 188 | 189 | # Install development + project dependencies 190 | if test -f dev-requirements.txt; then 191 | ".venv/$_venv_bin/python" -m pip --log ".venv/install-dev.log" install -r dev-requirements.txt 2>&1 | _venv_pip_log \ 192 | || echo >&2 "!!! WARN: pip install dev-requirements failed (RC=$?), see .venv/pip-install-dev.log for details" 193 | fi 194 | if test -f setup.py; then 195 | if grep "^# mkvenv: no-deps" "setup.py" >/dev/null; then 196 | echo "*** Not installing setup.py packages as requested" 197 | else 198 | ".venv/$_venv_bin/python" setup.py develop -U 2>&1 | _venv_pip_log 199 | fi 200 | echo 201 | ".venv/$_venv_bin/python" setup.py --name --version --author --author-email --license --description --url \ 202 | | tr -d \\r | xargs -d$'\n' printf "%s %s by %s <%s> [%s]\\n%s\\n%s\\n" || : 203 | else 204 | echo 205 | if test -f requirements.txt; then 206 | echo "*** No 'setup.py' found, installing requirements..." 207 | ".venv/$_venv_bin/python" -m pip --log ".venv/pip-install-req.log" install -r requirements.txt 2>&1 | _venv_pip_log 208 | else 209 | echo "*** No 'setup.py' or 'requirements.txt' found, all done." 210 | fi 211 | fi 212 | else 213 | # prevent constant prompting 214 | mkdir -p .venv 215 | fi 216 | fi 217 | if test -n "$SYSTEMROOT" -a -n "$WINDIR" && ! grep .venv/Scripts/activate .venv/Scripts/activate >/dev/null; then 218 | echo >>.venv/Scripts/activate \ 219 | 'export PATH=$(echo $PATH | sed -r -e '\''s~[\\]~/~g'\'' -e s~C:~/c~); hash -r' 220 | . .venv/Scripts/activate 221 | fi 222 | fi 223 | 224 | unset _venv_script _venv_bin _venv_name _venv_ask _venv_create _venv_develop _venv_pip_log _venv_base _venv_py_tk 225 | unset _venv_readlink _venv_temp _venv_virtualenv _venv_verbose _venv_py3 _venv_pip_req _venv_master_url _venv_choices 226 | eval $_venv_xtrace # restore xtrace state 227 | unset _venv_xtrace 228 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | .cache/ 38 | 39 | # Tests 40 | coverage.xml 41 | htmlcov/ 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Travis Project Descriptor 3 | # 4 | # See http://docs.travis-ci.com/user/build-configuration/ 5 | # 6 | 7 | # build matrix 8 | language: python 9 | python: 10 | - "2.7" 11 | - "3.4" 12 | 13 | # command to install dependencies 14 | install: 15 | - "pip install -r dev-requirements.txt" 16 | 17 | # command to run tests 18 | script: invoke selfcheck 19 | -------------------------------------------------------------------------------- /CHANGES.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Changelog 3 | ========= 4 | 5 | * :release:`0.6.0 <2021-06-21>` 6 | * :support:`8` Update default upstream version to 6.2.2 7 | * :support:`7` Changed download URLs to new GitHub hosting 8 | * :support:`0` Changed data URLs to v1.1 JSON format 9 | * Adapt or unset any environment variables you have, and do a full re-install 10 | with a full data retrieval (``rm -rf ~/.local/dependency-check/``) 11 | 12 | * :release:`0.5.0 <2020-01-08>` 13 | * :support:`0` Update default upstream version to 5.2.4 14 | * :support:`0` You MUST update your local installation to a 5.x version (see README) 15 | * :support:`0` You MUST also update ``DEPENDENCY_CHECK_NVD_URL`` in case you've set that, and the mirror it points to (use JSON compressed data files instead of XML) 16 | 17 | * :release:`0.2.0 <2017-10-09>` 18 | * :support:`0` Update default upstream version to 2.1.1 (from 1.3.1) 19 | * :bug:`2` Python 3 fixes (octal literal, urlopen) 20 | * :feature:`0` Added ``DEPENDENCY_CHECK_NVD_URL`` environment variable 21 | * :support:`0` Travis CI for Python 3.4 22 | 23 | * :release:`0.1.0 <2015-11-23>` 24 | * :feature:`0` Redirect calls to .sh / .bat launcher script 25 | * :feature:`0` Auto-install OWASP release archive 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # 2 | # Source Distribution Manifest 3 | # 4 | # More at https://docs.python.org/2/distutils/sourcedist.html 5 | 6 | include LICENSE requirements.txt *-requirements.txt *.rst *.py .env .gitignore .travis.yml 7 | include dependency_check.gif 8 | recursive-include tests *.py 9 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | dependency-check 2 | ================ 3 | 4 |  |Travis CI|  |GitHub Issues|  |License|  |Latest Version| 5 | 6 | 7 | Shim to easily install the `OWASP dependency-check-cli`_ tool into Python projects. 8 | 9 | .. contents:: **Table of Contents** 10 | 11 | .. _setup-start: 12 | 13 | :Code: https://github.com/jhermann/dependency-check-py#readme 14 | :Docs: https://github.com/jeremylong/dependencycheck#readme 15 | :CI: https://travis-ci.org/jhermann/dependency-check-py 16 | :Issues: https://github.com/jhermann/dependency-check-py/issues 17 | 18 | 19 | Overview 20 | -------- 21 | 22 | ``dependency-check`` scans application dependencies and checks whether they contain any published vulnerabilities 23 | (based on the NIST `NVD`_). 24 | It runs in the JVM, so you need some form of ``java`` available in your ``PATH``. 25 | The script should work on Linux, Mac OSX and Windows, but right now is only tested on Linux. 26 | 27 | 28 | Usage 29 | ----- 30 | 31 | After installation, you'll have the ``dependency-check`` command available that, on first use, 32 | will automatically download and install the OWASP release archive once for all projects. 33 | It'll then redirect any calls to that installation, meaning the downloaded NVD data is shared 34 | amongst projects. 35 | 36 | .. code-block:: 37 | 38 | dependency-check --disableAssembly -s . -o build --project "$(python ./setup.py --name)" \ 39 | --exclude ".git/**" --exclude ".venv/**" --exclude "**/__pycache__/**" --exclude ".tox/**" \ 40 | && xdg-open build/dependency-check-report.html 41 | 42 | Please see the `DependencyCheck site`_ for more configuration and usage details. 43 | 44 | To install from PyPI, add ``dependency-check`` to your ``dev-requirements.txt`` 45 | or a similar file. For more installation options, see the “Installation” section below. 46 | 47 | |Installation Demo| 48 | 49 | 50 | Customization 51 | ------------- 52 | 53 | Using environment variables, you can change the version and download location of the release archive, 54 | and the directory for the local installation. 55 | 56 | =============================== ============================================================================================== 57 | Variable Default 58 | =============================== ============================================================================================== 59 | ``DEPENDENCY_CHECK_VERSION`` ``6.2.2`` 60 | ``DEPENDENCY_CHECK_URL`` ``https://github.com/jeremylong/DependencyCheck/releases/download/v{version}/dependency-check-{version}-release.zip`` 61 | ``DEPENDENCY_CHECK_HOME`` ``~/.local/dependency-check`` 62 | ``DEPENDENCY_CHECK_NVD_URL`` *Use NIST NVD URLs* 63 | =============================== ============================================================================================== 64 | 65 | To update to a new version of the OWASP software, 66 | delete ``~/.local/dependency-check/bin/``, 67 | set ``DEPENDENCY_CHECK_VERSION`` to the new version number, 68 | and call ``dependency-check``. 69 | 70 | The variable ``DEPENDENCY_CHECK_NVD_URL`` can be used to point to a local copy of the various NVD feeds, 71 | in a flat hierarchy with compressed JSON files. 72 | 73 | .. code-block:: shell 74 | 75 | export DEPENDENCY_CHECK_NVD_URL='https://repo.local/nvd/nvdcve-1.1-%d.json.gz' 76 | 77 | If you set this, the options ``--cveUrlBase`` and ``--cveUrlModified`` will be added to each call. 78 | Note that the ``%d`` representing the year is replaced by ``modified`` for the latter. 79 | 80 | Remove the ``~/.local/dependency-check/data/`` directory to force a full data reload. 81 | 82 | 83 | Installation 84 | ------------ 85 | 86 | To just get the ``dependency-check`` CLI tool installed into your home, 87 | independent of any project, call ``python3 -m pip install --user dependency-check`` as usual, 88 | see `releases`_ for an overview of available versions. 89 | 90 | If you prefer an **isolated and easily removable venv installation**, 91 | consider using `dephell jail install dependency-check`_ instead. 92 | 93 | To get a bleeding-edge version from source, use these commands:: 94 | 95 | repo="jhermann/dependency-check-py" 96 | python3 -m pip install -r "https://raw.githubusercontent.com/$repo/master/requirements.txt" 97 | python3 -m pip install "https://github.com/$repo/archive/master.zip#egg=dependency-check" 98 | 99 | As a developer, to create a working directory for this project, call these commands:: 100 | 101 | git clone "https://github.com/jhermann/dependency-check-py.git" 102 | cd "dependency-check-py" 103 | command . .env --yes --develop 104 | invoke build --docs test check 105 | 106 | You might also need to follow some 107 | `setup procedures `_ 108 | to make the necessary basic commands available on *Linux*, *Mac OS X*, and *Windows*. 109 | 110 | 111 | Other Python Security Tools 112 | --------------------------- 113 | 114 | * `openstack/bandit`_ – Security linter designed to find common security issues in Python code, by static AST analysis. 115 | * `pyupio/safety`_ – Safety checks your installed dependencies for known security vulnerabilities. 116 | 117 | * `pyupio/safety-db`_ – A curated database of security vulnerabilities in Python packages. 118 | 119 | * `eliasgranderubio/dagda`_ – Static analysis of known vulnerabilities, trojans, viruses, malware & other malicious threats in Docker images, and runtime monitoring of containers for anomalous activities. 120 | * `anchore/anchore-engine`_ – A service for inspection, analysis and certification of container images, provided as a ready-to-deploy Docker container image. 121 | * `sonatype-nexus-community/jake`_ – An OSS Index integration to check your Conda environments for vulnerable Open Source packages. 122 | 123 | * `vintasoftware/python-linters-and-code-analysis`_ – Curated list of Python linters and code analysis tools. 124 | 125 | 126 | .. _`openstack/bandit`: https://github.com/openstack/bandit 127 | .. _`pyupio/safety`: https://github.com/pyupio/safety 128 | .. _`pyupio/safety-db`: https://github.com/pyupio/safety-db 129 | .. _`eliasgranderubio/dagda`: https://github.com/eliasgranderubio/dagda 130 | .. _`anchore/anchore-engine`: https://github.com/anchore/anchore-engine 131 | .. _`vintasoftware/python-linters-and-code-analysis`: https://github.com/vintasoftware/python-linters-and-code-analysis 132 | .. _`sonatype-nexus-community/jake`: https://github.com/sonatype-nexus-community/jake 133 | 134 | .. _`NVD`: https://nvd.nist.gov/ 135 | .. _`OWASP dependency-check-cli`: https://github.com/jeremylong/dependencycheck#readme 136 | .. _`DependencyCheck site`: https://www.owasp.org/index.php/OWASP_Dependency_Check 137 | .. _`pip script installer`: https://github.com/mitsuhiko/pipsi#pipsi 138 | .. _`releases`: https://github.com/jhermann/dependency-check-py/releases 139 | .. _`dephell jail install dependency-check`: https://dephell.readthedocs.io/cmd-jail-install.html 140 | 141 | .. |Installation Demo| image:: https://raw.githubusercontent.com/jhermann/dependency-check-py/master/dependency_check.gif 142 | 143 | .. |Travis CI| image:: https://api.travis-ci.org/jhermann/dependency-check-py.svg 144 | :target: https://travis-ci.org/jhermann/dependency-check-py 145 | .. |Coveralls| image:: https://img.shields.io/coveralls/jhermann/dependency-check-py.svg 146 | :target: https://coveralls.io/r/jhermann/dependency-check-py 147 | .. |GitHub Issues| image:: https://img.shields.io/github/issues/jhermann/dependency-check-py.svg 148 | :target: https://github.com/jhermann/dependency-check-py/issues 149 | .. |License| image:: https://img.shields.io/pypi/l/dependency-check.svg 150 | :target: https://github.com/jhermann/dependency-check-py/blob/master/LICENSE 151 | .. |Development Status| image:: https://img.shields.io/pypi/status/dependency-check.svg 152 | :target: https://pypi.python.org/pypi/dependency-check/ 153 | .. |Latest Version| image:: https://img.shields.io/pypi/v/dependency-check.svg 154 | :target: https://pypi.python.org/pypi/dependency-check/ 155 | .. |Download format| image:: https://img.shields.io/pypi/format/dependency-check.svg 156 | :target: https://pypi.python.org/pypi/dependency-check/ 157 | .. |Downloads| image:: https://img.shields.io/pypi/dw/dependency-check.svg 158 | :target: https://pypi.python.org/pypi/dependency-check/ 159 | -------------------------------------------------------------------------------- /dependency_check.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhermann/dependency-check-py/ca1dbf876c28f7bee0a36b61eba9cb3761659260/dependency_check.gif -------------------------------------------------------------------------------- /dependency_check.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | dependency-check - Shim to easily install OWASP dependency-check-cli into Python projects. 4 | 5 | Copyright © 2015 – 2020 Jürgen Hermann 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | """ 19 | from __future__ import absolute_import, unicode_literals, print_function 20 | 21 | __version__ = '0.6.0' 22 | __author__ = 'Jürgen Hermann' 23 | __author_email__ = 'jh@web.de' 24 | 25 | 26 | import os 27 | import sys 28 | import shutil 29 | try: 30 | from urllib.request import urlopen 31 | except ImportError: 32 | from urllib2 import urlopen 33 | import zipfile 34 | import tempfile 35 | import subprocess 36 | from contextlib import closing 37 | 38 | 39 | DEPENDENCY_CHECK_VERSION = '6.2.2' 40 | DEPENDENCY_CHECK_URL = 'https://github.com/jeremylong/DependencyCheck/releases/download/v{version}/dependency-check-{version}-release.zip' 41 | 42 | 43 | def install_path(): 44 | """Return the target path for installation of ``dependency-check-cli``.""" 45 | return os.environ.get('DEPENDENCY_CHECK_HOME', os.path.expanduser('~/.local/dependency-check')).rstrip(os.sep) 46 | 47 | 48 | def install(): 49 | """Install the ZIP release.""" 50 | dc_home = install_path() 51 | dc_command = os.path.join(dc_home, 'bin', 'dependency-check' + ('.bat' if sys.platform == 'win32' else '.sh')) 52 | 53 | if not os.path.isfile(dc_command): 54 | # Install `dependency-check-cli` release 55 | dc_url = os.environ.get('DEPENDENCY_CHECK_URL', DEPENDENCY_CHECK_URL) 56 | dc_version = os.environ.get('DEPENDENCY_CHECK_VERSION', DEPENDENCY_CHECK_VERSION) 57 | dc_url = dc_url.format(version=dc_version) 58 | install_ok = False 59 | 60 | with tempfile.NamedTemporaryFile(suffix='.zip', prefix='dependency-check-', delete=False) as zip_temp: 61 | try: 62 | print("Downloading '{}'...".format(dc_url)) 63 | with closing(urlopen(dc_url)) as url_handle: 64 | shutil.copyfileobj(url_handle, zip_temp) 65 | zip_temp.close() 66 | 67 | print("Unpacking '{}' to '{}'...".format(zip_temp.name, dc_home)) 68 | if not os.path.isdir(dc_home): 69 | os.makedirs(dc_home) 70 | with closing(zipfile.ZipFile(zip_temp.name)) as zip_handle: 71 | for member in zip_handle.infolist(): # bogus pylint: disable=no-member 72 | out_path = dc_home + os.sep + member.filename.split('/', 1)[1] 73 | if member.filename.endswith('/'): 74 | if not os.path.isdir(out_path): 75 | os.makedirs(out_path) 76 | else: 77 | with closing(zip_handle.open(member)) as inp: # bogus pylint: disable=no-member 78 | with open(out_path, 'wb') as out: 79 | shutil.copyfileobj(inp, out) 80 | os.chmod(os.path.join(dc_home, 'bin', 'dependency-check.sh'), 0o755) 81 | install_ok = True 82 | finally: 83 | if not install_ok and os.path.exists(dc_command): 84 | os.remove(dc_command) # mark failed install as incomplete 85 | if os.path.exists(zip_temp.name): 86 | os.remove(zip_temp.name) 87 | 88 | return dc_command 89 | 90 | 91 | def dc_opts(): 92 | """Return additional options to inject into the dependency-check command.""" 93 | opts = [] 94 | # Default: https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz 95 | nvd_base_url = os.environ.get('DEPENDENCY_CHECK_NVD_URL', '') 96 | 97 | if nvd_base_url: 98 | opts.extend([ 99 | '--cveUrlBase', nvd_base_url, 100 | '--cveUrlModified', nvd_base_url.replace('%d', 'modified'), 101 | ]) 102 | 103 | return opts 104 | 105 | 106 | def run(): 107 | """Execute main loop.""" 108 | try: 109 | # Delegate to `dependency-check-cli` 110 | dc_command = install() 111 | sys.exit(subprocess.call([dc_command] + dc_opts() + sys.argv[1:])) 112 | except KeyboardInterrupt: 113 | sys.stderr.flush() 114 | sys.exit(2) 115 | 116 | 117 | if __name__ == '__main__': 118 | run() 119 | -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Development requirements 3 | # 4 | 5 | invoke==1.4.1 6 | rituals==0.4.1 7 | #https://github.com/jhermann/rituals/archive/master.zip#egg=rituals 8 | 9 | pytest==4.6.9 10 | pytest-cov==2.8.1 11 | pytest-mock==2.0.0 12 | pytest-spec==2.0.0 13 | tox==3.14.5 14 | pylint==2.4.4 15 | bpython==0.18 16 | yolk3k==0.9 17 | pip-upgrader==1.4.15 18 | 19 | twine==3.1.1 20 | 21 | # -r test-requirements.txt 22 | -r requirements.txt 23 | -e . 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Install requirements 3 | # 4 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Configuration for setuptools 3 | # 4 | 5 | [egg_info] 6 | #tag_build = .dev 7 | #tag_date = false 8 | 9 | 10 | [sdist] 11 | formats = zip 12 | 13 | 14 | [bdist_wheel] 15 | # If you set this to 1, make sure you have a proper Travis CI build matrix, 16 | # and that your Trove classifiers state you support Python 2 and 3 17 | universal = 1 18 | 19 | 20 | [flake8] 21 | ignore = E124,E128 22 | max-line-length = 132 23 | 24 | 25 | # py.test and Coverage 26 | # 27 | 28 | [tool:pytest] 29 | norecursedirs = .* *.egg *.egg-info bin dist include lib local share static docs 30 | python_files = tests/test_*.py 31 | addopts = --spec 32 | 33 | markers = 34 | cli: command line interface integration tests. 35 | integration: integration tests. 36 | online: tests that need an Internet connection. 37 | 38 | 39 | [run] 40 | branch = True 41 | omit = test_*.py 42 | 43 | [report] 44 | ignore_errors = True 45 | 46 | # Regex 'find' matches for lines to exclude from consideration 47 | exclude_lines = 48 | pragma: *no-?cover 49 | raise NotImplementedError 50 | if __name__ == .__main__.: 51 | except ImportError: 52 | 53 | [xml] 54 | output = build/coverage.xml 55 | 56 | [html] 57 | directory = build/coverage_html 58 | 59 | 60 | # Tox configuration, for details see 61 | # 62 | # http://tox.testrun.org/ 63 | # 64 | # $ . .env "--yes" "--develop" 65 | # $ tox 66 | 67 | [tool:tox] 68 | envlist = py3, flake8 69 | 70 | [testenv] 71 | basepython = 72 | {py3,flake8}: python3 73 | deps = 74 | -r./dev-requirements.txt 75 | commands = 76 | pytest -c {toxinidir}/setup.cfg --color=yes --cov=dependency_check \ 77 | --cov-config=setup.cfg --cov-report=term --cov-report=html --cov-report=xml \ 78 | {posargs} 79 | 80 | [testenv:py3] 81 | 82 | [testenv:flake8] 83 | deps = 84 | flake8==3.3.0 85 | pep8==1.7.0 86 | 87 | ; for now just informational (exit-zero) 88 | commands = 89 | flake8 --count --statistics --exit-zero *.py 90 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # pylint: disable=locally-disabled, invalid-name, wrong-import-position 4 | """ 5 | dependency-check - Shim to easily install OWASP dependency-check-cli into Python projects. 6 | 7 | This setuptools script follows the DRY principle and tries to 8 | minimize repetition of project metadata by loading it from other 9 | places (like the script module's ``__*__`` attributes). Incidently, 10 | this makes the script almost identical between different projects. 11 | 12 | It is also importable (by using the usual ``if __name__ == '__main__'`` 13 | idiom), and exposes the project's setup data in a ``project`` dict. 14 | This allows other tools to exploit the data assembling code contained 15 | in here, and again supports the DRY principle. The ``rituals`` package 16 | uses that to provide Invoke tasks that work for any project, based on 17 | its project metadata. 18 | 19 | Copyright © 2015 Jürgen Hermann 20 | 21 | Licensed under the Apache License, Version 2.0 (the "License"); 22 | you may not use this file except in compliance with the License. 23 | You may obtain a copy of the License at 24 | 25 | http://www.apache.org/licenses/LICENSE-2.0 26 | 27 | Unless required by applicable law or agreed to in writing, software 28 | distributed under the License is distributed on an "AS IS" BASIS, 29 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 30 | See the License for the specific language governing permissions and 31 | limitations under the License. 32 | """ 33 | 34 | project = dict( 35 | name='dependency-check', 36 | url='https://github.com/jhermann/dependency-check-py', 37 | license="Apache 2.0", 38 | keywords='owasp, security, vulnerability, quality-assurance', 39 | py_modules=['dependency_check'], 40 | 41 | install_requires=[], 42 | 43 | entry_points={ 44 | "console_scripts": [ 45 | "dependency-check = dependency_check:run", 46 | ], 47 | }, 48 | 49 | # Added by the code below: 50 | # version author author_email (from script module) 51 | # description (from doc string above) 52 | # long_description (from README) 53 | # classifiers (see below) 54 | ) 55 | 56 | classifiers = """ 57 | # Details at http://pypi.python.org/pypi?:action=list_classifiers 58 | Development Status :: 5 - Production/Stable 59 | Programming Language :: Python 60 | Programming Language :: Python :: 2 61 | Programming Language :: Python :: 2.7 62 | Programming Language :: Python :: 3 63 | Programming Language :: Python :: 3.4 64 | Environment :: Console 65 | Intended Audience :: Developers 66 | Intended Audience :: Information Technology 67 | Intended Audience :: System Administrators 68 | License :: OSI Approved :: Apache Software License 69 | Operating System :: OS Independent 70 | Topic :: Security 71 | Topic :: Software Development :: Quality Assurance 72 | Topic :: Utilities 73 | """ 74 | 75 | 76 | # Beyond this point, code is not project-specific 77 | import io 78 | import os 79 | import re 80 | import sys 81 | 82 | try: 83 | from setuptools import setup 84 | except ImportError as exc: 85 | raise RuntimeError("Cannot install '{0}', setuptools is missing ({1})" 86 | .format(project['name'], exc)) 87 | 88 | project_root = os.path.abspath(os.path.dirname(__file__)) 89 | script_name = os.path.join(project_root, project['py_modules'][0] + '.py') 90 | expected_keys = "version author author_email".split() 91 | with io.open(script_name, encoding='utf-8') as handle: 92 | for line in handle: 93 | match = re.match(r"""^__({})__ += (?P['"])(.+?)(?P=q)$""" 94 | .format('|'.join(expected_keys)), line) 95 | if match: 96 | project[match.group(1)] = match.group(3) 97 | 98 | project.update(dict( 99 | description=__doc__.split('.')[0].split(' - ', 1)[1].strip(), 100 | long_description=(io.open('README.rst', encoding='UTF-8').read() 101 | .split('\n.. _setup-start:', 1)[-1].strip()), 102 | classifiers=[i.strip() 103 | for i in classifiers.splitlines() 104 | if i.strip() and not i.strip().startswith('#')], 105 | keywords=project['keywords'].replace(',', ' ').strip().split(), 106 | )) 107 | 108 | # Ensure 'setup.py' is importable by other tools, to access the project's metadata 109 | __all__ = ['project', 'project_root'] 110 | if __name__ == '__main__': 111 | if '--metadata' in sys.argv[:2]: 112 | import json 113 | json.dump(project, sys.stdout, default=repr, indent=4, sort_keys=True) 114 | sys.stdout.write('\n') 115 | else: 116 | setup(**project) 117 | -------------------------------------------------------------------------------- /tasks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # pylint: disable=wildcard-import, unused-wildcard-import, bad-continuation 3 | """ Project automation for Invoke. 4 | """ 5 | from __future__ import absolute_import, unicode_literals 6 | 7 | import subprocess 8 | 9 | from rituals import config 10 | from rituals.easy import * # pylint: disable=redefined-builtin 11 | 12 | config.set_flat_layout() 13 | 14 | @task(pre=[clean]) # pylint: disable=undefined-variable 15 | def selfcheck(ctx): 16 | """Perform integration tests.""" 17 | project = subprocess.check_output('python ./setup.py --name'.split()).strip() 18 | ctx.run("dependency-check --disableAssembly -s . -o build --project '{}'".format(project)) 19 | 20 | namespace.add_task(selfcheck) 21 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=unused-import 2 | """ 3 | py.test Configuration Module. 4 | """ 5 | import pytest 6 | -------------------------------------------------------------------------------- /tests/test_cli.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=missing-function-docstring 2 | """ 3 | Test the CLI. 4 | """ 5 | import os 6 | import shutil 7 | import tempfile 8 | 9 | import dependency_check 10 | 11 | ENV_NVD_URL = 'DEPENDENCY_CHECK_NVD_URL' 12 | 13 | def test_entry_point(): 14 | assert callable(dependency_check.run) 15 | 16 | 17 | def test_install(): 18 | stage = tempfile.mkdtemp(prefix='dc-test-') 19 | try: 20 | os.environ['DEPENDENCY_CHECK_HOME'] = stage 21 | cmd = dependency_check.install() 22 | del os.environ['DEPENDENCY_CHECK_HOME'] 23 | 24 | assert cmd.endswith('.sh') 25 | finally: 26 | shutil.rmtree(stage) 27 | 28 | 29 | def test_default_options(): 30 | if ENV_NVD_URL in os.environ: 31 | del os.environ[ENV_NVD_URL] 32 | options = dependency_check.dc_opts() 33 | 34 | assert not options 35 | 36 | 37 | def test_options_with_custom_url(): 38 | os.environ[ENV_NVD_URL] = 'http://example.com' 39 | options = dependency_check.dc_opts() 40 | 41 | assert options[0].startswith('--cveUrl') 42 | assert options[1].startswith(os.environ[ENV_NVD_URL]) 43 | --------------------------------------------------------------------------------