DEV Community

Cover image for Auditing your python environment
Kevin Tewouda
Kevin Tewouda

Posted on • Edited on

Auditing your python environment

We have more and more hackers trying to steal information from users using malicious packages. Therefore, it is important to check frequently the dependencies of your project to know if vulnerabilities have been found. In this short tutorial, I will introduce you to two tools to help you audit your dependencies.

safety

The first one is safety. It is maintained by the pyup team which uses their custom safety
database. It comes in two flavors:

  • An open source version that we can freely use. It is updated once a month.
  • A paid version that is updated frequently (more than once a month).

installation

To install the package, type the following command in your terminal:

$ pip install safety
Enter fullscreen mode Exit fullscreen mode

or if you are using a more advanced python package installer like poetry:

$ poetry add -D safety
Enter fullscreen mode Exit fullscreen mode

If you don't want to install it directly in your project, and you are using GitHub, there is an official GitHub action you can use in your CI.

 - uses: pyupio/safety@v1
     # if you subscribed to a paid plan, you can insert your key like the following snippet
     # it assumes that you have a secret key called SAFETY_API_KEY and define under
     # Settings -> Secrets -> Actions in GitHub admin.
     with:
       api-key: ${{ secrets.SAFETY_API_KEY }}
Enter fullscreen mode Exit fullscreen mode

usage

To test safety, we will install flask with version 0.5.

$ pip install flask==0.5
# or
$ poetry add flask==0.5
Enter fullscreen mode Exit fullscreen mode

The usage is pretty straightforward. To scan vulnerabilities in your current python environment, you type:

$ safety check
Enter fullscreen mode Exit fullscreen mode

You will see an output like the following:

...
 REPORT 

  Safety v2.1.1 is scanning for Vulnerabilities...
  Scanning dependencies in your environment:

  -> /home/kevin/.cache/pypoetry/virtualenvs/orm-L9juRWWT-py3.8/lib/python3.8/site-packages

  Using non-commercial database
  Found and scanned 64 packages
  Timestamp 2022-08-17 22:52:00
  3 vulnerabilities found
  0 vulnerabilities ignored

+=======================================================================================================================+
 VULNERABILITIES FOUND 
+=======================================================================================================================+

-> Vulnerability found in flask version 0.5
   Vulnerability ID: 38654
   Affected spec: <0.12.3
   ADVISORY: Flask 0.12.3 includes a fix for CVE-2019-1010083: Unexpected memory usage. The impact is denial of service. 
   The attack vector is crafted encoded JSON data.
   NOTE: this may overlap CVE-2018-1000656.https://github.com/pallets/flask/pull/2695/commits/0e1e9a04aaf29ab78f721cfc79ac2a691f6e3929
   CVE-2019-1010083
   For more information, please visit https://pyup.io/vulnerabilities/CVE-2019-1010083/38654/


 Scan was completed. 3 vulnerabilities were found. 
 ...
+=======================================================================================================================+
   REMEDIATIONS

  3 vulnerabilities were found in 1 package. For detailed remediation & fix recommendations, upgrade to a commercial license. 
...
Enter fullscreen mode Exit fullscreen mode

If you want a more detailed output, you can run the previous command with the flag --full-report:

$ safety check --full-report
Enter fullscreen mode Exit fullscreen mode

Note: as you can see in the output, it is only when you subscribed to a paid plan that you have suggestions on how to fix this vulnerability issue. This is not the case with the second tool I will introduce.
If you just want to see the vulnerable packages without further information, you can run:

$ safety check --bare
flask
Enter fullscreen mode Exit fullscreen mode

You can also scan packages through a requirements file.

$ safety check -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Or scan a single package.

$ echo "package-to-check==0.1" | safety check --stdin
Enter fullscreen mode Exit fullscreen mode

By default, the output is in text format, but you can change it in JSON if you want with the --output option:

$ safety check --output json
Enter fullscreen mode Exit fullscreen mode

pip-audit

The second tool I want to introduce to you is pip-audit. It is maintained by folks at Trails of Bit with some Google support. It uses the Pypa Advisory Database via the PyPI JSON API as a source of vulnerability reports.

installation

You can install it using pip or poetry like the following:

$ pip install pip-audit
# or
$ poetry add -D pip-audit
Enter fullscreen mode Exit fullscreen mode

If you are using GitHub, there is a GitHub action you can use:

jobs:
  pip-audit:
    steps:
      - uses: trailofbits/gh-action-pip-audit@v0.0.4
        # if you use a requirements file, you can add the following
        with:
          inputs: requirements.txt
Enter fullscreen mode Exit fullscreen mode

More information about how to configure it can be found here.

You can also use a pre-commit hook, although I will not recommend it since it will always trigger a network request and reduce the developer experience.

- repo: https://github.com/trailofbits/pip-audit
    rev: v2.4.3
    hooks:
      - id: pip-audit
        args: [ "-r", "requirements.txt" ]

ci:
  # Leave pip-audit to only run locally and not in CI
  # pre-commit.ci does not allow network calls
  skip: [ pip-audit ]
Enter fullscreen mode Exit fullscreen mode

usage

We will still consider having the flask package with version 0.5 in our environment. To run pip-audit in our current python environment, we can type:

$ pip-audit
Enter fullscreen mode Exit fullscreen mode

We will have an output like the following:

Found 2 known vulnerabilities in 1 package
Name  Version ID             Fix Versions
----- ------- -------------- ------------
flask 0.5     PYSEC-2019-179 1.0
flask 0.5     PYSEC-2018-66  0.12.3
Enter fullscreen mode Exit fullscreen mode

For a more detailed output use the --desc flag:

$ pip-audit --desc
Enter fullscreen mode Exit fullscreen mode

If you want to fix the issue, you can use the --fix flag. The command will install the minimal version fixing the issue.
Bear in mind that this workflow only works if you are using pip as your package dependency manager. If you are using another tool like pipenv or poetry, you probably want to see the fixed version without installing it with pip otherwise you will break your dependencies workflow. To achieve that, you must append
the --dry-run flag to the --fix one.

$ pip-audit --fix --dry-run
INFO:pip_audit._cli:Dry run: would have upgraded Flask to 1.0
Found 2 known vulnerabilities in 1 package and fixed 0 vulnerabilities in 0 packages
Name  Version ID             Fix Versions
----- ------- -------------- ------------
flask 0.5     PYSEC-2019-179 1.0
flask 0.5     PYSEC-2018-66  0.12.3
Enter fullscreen mode Exit fullscreen mode

Now we see that the minimum version to solve the flask issue is 1.0. If you are using poetry, you need to change the version in pyproject.toml file with something like ^1.0 and run the following command:

$ poetry update flask
Enter fullscreen mode Exit fullscreen mode

Now we can sleep well 😁.

pip-audit can also scan a requirements file:

$ pip-audit -r ./requirements.txt
Enter fullscreen mode Exit fullscreen mode

If you are not in a virtual environment and use the pyproject.toml file to list
your dependencies, you can run:

# this assumes pyproject.toml is in the current directory
$ pip-audit .
Enter fullscreen mode Exit fullscreen mode

By default, the output is in columns format, you can change it with the -f option. There are many supported formats like markdown, json, etc... To know more about the different formats supported you can type pip-audit --help in your
terminal. Example of the use of the json format:

$ pip-audit -f json | python -m json.tool
Enter fullscreen mode Exit fullscreen mode

which audit tool to use in your project?

The answer to this question depends on your needs and constraints. Here are some considerations to take into account when making your decision.

  • safety has a company behind it that dedicates its time finding vulnerabilities in python packages ahead of official CVE.
  • To make the best use of safety i.e. have the best up-to-date vulnerability database, you should use a paid plan. You need to be sure you or your company has the budget for that.
  • pip-audit is more open source than safety since the management of the database is transparent for all users.
  • pip-audit provides a hint to fix a found vulnerability, safety doesn't do that unless you subscribed to a paid plan.
  • pip-audit may be integrated into pip in the future.

This is all for this tutorial, hope you enjoyed it. Take care of yourself and see you next time! 😁


If you like my article and want to continue learning with me, don’t hesitate to follow me here and subscribe to my newsletter on substack 😉

Top comments (0)