Skip to content

Commit fa52dcb

Browse files
authored
Feature/372 create converter for pip audit vulnerabilities (#387)
* Add JSON output for pip-audit for security pipeline - The current implementation chain parses a CVE from the title. While we could initially send non-CVEs, the difficulty would lie in updating the subsequent code to accomodate that. - For more information, see #387 (comment) * Add documentation for GitHub security-issues action * Run changelog:updated check when on a branch != main * Fix typo in dependencies & remove unused import * Fix formatting missed in previous work * Remove redundant variable usage * Remove dependency:audit from CI pipelines as unnecessary and reduce options
1 parent 31cf239 commit fa52dcb

File tree

15 files changed

+483
-120
lines changed

15 files changed

+483
-120
lines changed

.github/workflows/checks.yml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ jobs:
5454
python-version: "3.9"
5555

5656
- name: Run changelog update check
57+
if: ${{ github.ref != 'refs/heads/main' }}
5758
run: poetry run nox -s changelog:updated
5859

5960
build-matrix:
@@ -136,25 +137,6 @@ jobs:
136137
path: .security.json
137138
include-hidden-files: true
138139

139-
Vulnerabilities:
140-
name: Check Vulnerabilities (Python-${{ matrix.python-version }})
141-
needs: [ Version-Check, build-matrix ]
142-
runs-on: ubuntu-24.04
143-
strategy:
144-
matrix: ${{ fromJson(needs.build-matrix.outputs.matrix) }}
145-
146-
steps:
147-
- name: SCM Checkout
148-
uses: actions/checkout@v4
149-
150-
- name: Setup Python & Poetry Environment
151-
uses: ./.github/actions/python-environment
152-
with:
153-
python-version: ${{ matrix.python-version }}
154-
155-
- name: Run Package vulnerabilities Check
156-
run: poetry run nox -s dependency:audit
157-
158140
Format:
159141
name: Format Check
160142
runs-on: ubuntu-24.04

doc/_static/idioms/context_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def chdir(path):
1313

1414
def initialize(directory):
1515
with chdir(directory) as _working_dir:
16-
with open('some-file.txt', 'w') as f:
16+
with open("some-file.txt", "w") as f:
1717
f.write("Some content")
1818

1919

@@ -23,7 +23,7 @@ def initialize(directory):
2323

2424
def initialize(directory):
2525
with chdir(directory) as _working_dir:
26-
with open('some-file.txt', 'w') as f:
26+
with open("some-file.txt", "w") as f:
2727
f.write("Some content")
2828

2929

@@ -35,6 +35,6 @@ def initialize(directory):
3535
old_dir = os.getcwd()
3636
os.chdir(directory)
3737
os.chdir(old_dir)
38-
with open('some-file.txt', 'w') as f:
38+
with open("some-file.txt", "w") as f:
3939
f.write("Some content")
4040
os.chdir(old_dir)

doc/changes/unreleased.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* [#73](https://github.com/exasol/python-toolbox/issues/73): Added nox target for auditing work spaces in regard to known vulnerabilities
66
* [#65](https://github.com/exasol/python-toolbox/issues/65): Added a Nox task for checking if the changelog got updated.
77
* [#369](https://github.com/exasol/python-toolbox/issues/369): Removed option `-v` for `isort`
8+
* [#372](https://github.com/exasol/python-toolbox/issues/372): Added conversion from pip-audit JSON to expected GitHub Issue format
89

910
## ⚒️ Refactorings
1011
* [#388](https://github.com/exasol/python-toolbox/issues/388): Switch GitHub workflows to use pinned OS version

doc/design.rst

Lines changed: 116 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Overview
2424
This project mainly serves three main purposes:
2525

2626
#. Provide library code, scripts and commands for common developer tasks within a python project.
27-
#. Provide and maintain commonly required functionality for python project
27+
#. Provide and maintain commonly required functionality for a python project
2828
* Common Projects Tasks
2929
- apply code formatters
3030
- lint project
@@ -33,6 +33,7 @@ This project mainly serves three main purposes:
3333
- run integration tests
3434
- determine code coverage
3535
- build-, open-, clean- documentation
36+
- creates GitHub Issues for vulnerabilities
3637
* CI (verify PR's and merges)
3738
* CI/CD (verify and publish releases)
3839
* Build & Publish Documentation (verify and publish documentation)
@@ -45,16 +46,16 @@ Design
4546

4647
Design Principles
4748
+++++++++++++++++
48-
* This project needs to be thought of as development dependency only!
49-
- Library code should not imported/used in non development code of the projects
49+
* This project needs to be thought of as a development dependency only!
50+
- Library code should not imported/used in non-development code of the projects
5051
* Convention over configuration
5152
- Being able to assume conventions reduces the code base/paths significantly
5253
- First thought always should be: Can it be done easily by using/applying convention(s)
5354
- Use configuration if it's more practical or if it simplifies transitioning projects
54-
* Provide extension points (hooks) where for project specific behaviour
55+
* Provide extension points (hooks) for project specific behaviour
5556
- If it can't be a convention or configuration setting
5657
- If having something as a convention or configuration significantly complicates the implementation
57-
- If you have a obvious use case within at least one project
58+
- If you have an obvious use case within at least one project
5859
* KISS (Keep It Stupid Simple)
5960
- This project shall simplify the work of the developer, not add a burden on top
6061
- Try to automate as much as possible
@@ -64,7 +65,7 @@ Design Principles
6465
.. note::
6566

6667
It is clear that not everything can and will be automated right from the beginning,
67-
but there should be continues effort to improve the work of the developers.
68+
but there should be continuous effort to improve the work of the developers.
6869

6970
e.g.:
7071

@@ -114,18 +115,18 @@ Design Principles
114115

115116
Design Decisions
116117
++++++++++++++++
117-
* Whenever possible tools provided or required by the toolbox should get their configuration from the projects *pyproject.toml* file.
118-
* Whenever a more dynamic configuration is needed it should be made part of the config object in the projects *noxconfig.py* file.
119-
* The required standard tooling used within the toolbox will obey what have been agreed upon in the exasol `python-styleguide <https://exasol.github.io/python-styleguide/guides/tooling.html>`_.
120-
* As Task runner the toolbox will be using nox
118+
* Whenever possible, tools provided or required by the toolbox should get their configuration from the projects *pyproject.toml* file.
119+
* Whenever a more dynamic configuration is needed, it should be made part of the config object in the projects *noxconfig.py* file.
120+
* The required standard tooling used within the toolbox will obey what has been agreed upon in the Exasol `python-styleguide <https://exasol.github.io/python-styleguide/guides/tooling.html>`_.
121+
* For a task runner, the toolbox will be using nox
121122
.. warning:: Known Issue(s)
122123

123124
Nox tasks should not call (notify) other nox tasks. This can lead to unexpected behaviour
124125
due to the fact that the job/task queue will `execute a task only once <https://nox.thea.codes/en/stable/config.html#nox.sessions.Session.notify>`_.
125126

126-
Therefore all functionality which need to be reused or called multiple times within or by different nox tasks,
127-
should be provided by python code (e.g. functions) which is receiving a nox session as argument
128-
but isn't annotated as a nox session/task (`@nox.session <https://nox.thea.codes/en/stable/config.html#defining-sessions>`_).
127+
Therefore, all functionality, which needs to be re-used, called multiple times calls, or is used by different nox tasks,
128+
should be provided by python code (e.g. functions) which receives a nox session as an argument, but the code itself
129+
shall not be annotated as a nox session/task (`@nox.session <https://nox.thea.codes/en/stable/config.html#defining-sessions>`_).
129130

130131
.. note::
131132

@@ -136,11 +137,11 @@ Design Decisions
136137
* It is already used by a couple of our projects, so the team is familiar with it
137138
* The author of the toolbox is very familiar with it
138139

139-
That said, no in depth evaluation of other tools haven been done.
140+
That said, no in-depth evaluation of other tools has been done.
140141

141142

142-
* Workflows (CI/CD & Co.) will be github actions based
143-
- This is the standard tool within the exasol integration team
143+
* Workflows (CI/CD & Co.) will be GitHub Actions-based
144+
- This is the standard tool within the Exasol Integration Team
144145
* Workflows only shall provide an execution environment and orchestrate the execution itself
145146

146147
Detailed Design
@@ -150,36 +151,15 @@ Tasks
150151
~~~~~
151152
.. todo:: Add diagram configuration and tasks (noxfile.py + noxconfig.py + exasol.toolbox)
152153

153-
.. list-table::
154-
:header-rows: 1
155-
:widths: 30 70
154+
To view all the defined nox tasks & their definitions use:
156155

157-
* - Tasks
158-
- Description
159-
* - fix
160-
- Runs all automated fixes on the code base
161-
* - check
162-
- Runs all available checks on the project
163-
* - lint
164-
- Runs the linter on the project
165-
* - type-check
166-
- Runs the type checker on the project
167-
* - unit-tests
168-
- Runs all unit tests
169-
* - integration-tests
170-
- Runs the all integration tests
171-
* - coverage
172-
- Runs all tests (unit + integration) and reports the code coverage
173-
* - build-docs
174-
- Builds the project documentation
175-
* - open-docs
176-
- Opens the built project documentation
177-
* - clean-docs
178-
- Removes the documentations build folder
156+
.. code-block:: shell
157+
158+
poetry run nox -l
179159
180160
Workflows
181161
~~~~~~~~~
182-
.. todo:: Add diagram of github workflows and interaction
162+
.. todo:: Add diagram of GitHub workflows and interaction
183163

184164

185165
Available Workflows
@@ -208,7 +188,91 @@ _________________
208188
* - Action
209189
- Description
210190
* - python-environment
211-
- Sets up an appropriate poetry based python environment
191+
- Sets up an appropriate poetry-based python environment
192+
* - security-issues
193+
- Takes a JSON of known vulnerabilities affecting a repo & creates GitHub Issues
194+
in said repo for any vulnerabilities, which do not yet have a GitHub Issue
195+
196+
security-issues
197+
^^^^^^^^^^^^^^^
198+
The `security-issues/action.yml` creates GitHub Issues for known vulnerabilities
199+
for `maven <https://sonatype.github.io/ossindex-maven/maven-plugin/>`_ and `pip-audit <https://pypi.org/project/pip-audit/>`_.
200+
The following steps are taken:
201+
202+
1. Convert a JSON of known vulnerabilities into a common format (`class Issue`)
203+
2. Filter out vulnerabilities which already have an existing GitHub Issue via CVE
204+
3. Create new GitHub Issues
205+
4. Return a JSON of the newly created GitHub Issues
206+
207+
Input Variants
208+
""""""""""""""
209+
An input variant would be passed in as a string-encoded JSON.
210+
211+
`maven` (with `ossindex-audit <https://sonatype.github.io/ossindex-maven/maven-plugin/ossindex-audit/>`_)
212+
213+
.. code-block:: json
214+
215+
{
216+
"vulnerable": {
217+
"<package_name>@<package_version>:compile": {
218+
"coordinates": "<package_name>@<package_version>",
219+
"description": "<package_description>",
220+
"reference": "<oss_url_for_vuln>",
221+
"vulnerabilities": [
222+
{
223+
"id": "<vuln_id>",
224+
"displayName": "<vuln_name>",
225+
"title": "<vuln_title>",
226+
"description": "<vuln_description>",
227+
"cvssScore": 7.5,
228+
"cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
229+
"cwe": "<cwe_vuln_id>",
230+
"cve": "<cve_vuln_id>",
231+
"reference": "<oss_url_for_vuln>",
232+
"externalReferences": ["<vuln_reference_url>"],
233+
}
234+
],
235+
},
236+
}
237+
}
238+
239+
`pip-audit` (via `nox -s dependency:audit`)
240+
241+
.. code-block:: json
242+
243+
{
244+
"dependencies": [
245+
{
246+
"name": "<package_name>",
247+
"version": "<package_version>",
248+
"vulns":
249+
[
250+
{
251+
"id": "<vuln_id>",
252+
"fix_versions": ["<fix_version>"],
253+
"aliases": ["<vuln_id2>"],
254+
"description": "<vuln_description>"
255+
}
256+
]
257+
}
258+
]
259+
}
260+
261+
Known Issues
262+
""""""""""""
263+
The `security-issues/action.yml` assumes that eventually every known vulnerability will
264+
be associated with a singular CVE.
265+
266+
* This can be problematic as vulnerabilities may be initially reported to different
267+
services and not receive a CVE until a few days later or, in some cases, never. This
268+
could mean that some vulnerabilities are initially missed or, in some cases,
269+
never propagated by our action.
270+
* Additionally, reporting tools like `pip-audit` must link a vulnerability with the
271+
different vulnerability IDs from different reporting services. Typically, this is done
272+
by selecting 1 of the vulnerability IDs as the unique identifier of the vulnerability.
273+
This, as is the case for `pip-audit`, may not be the CVE, so it is possible if the
274+
linked vulnerability IDs were to change (i.e. wrongly linked CVE) that we could end
275+
up with multiple GitHub Issues for the same underlying vulnerability.
212276

213277

214278
Known Issues
@@ -222,7 +286,7 @@ Passing files as individual arguments on the CLI
222286

223287
**Description:**
224288

225-
As of today selection of python files for linting, formatting etc. is done by passing all relevant python files as individual argument(s)
289+
As of today selection of Python files for linting, formatting etc. is done by passing all relevant python files as individual argument(s)
226290
to the tools used/invoked by the python toolbox.
227291

228292
**Downsides:**
@@ -312,7 +376,7 @@ While Nox isn't a perfect fit, it still meets most of our requirements for a tas
312376

313377
**Rationale/History:**
314378

315-
Why Nox was choosen:
379+
Why Nox was chosen:
316380

317381
- No additional language(s) required: There was no need to introduce extra programming languages or binaries, simplifying the development process.
318382
- Python-based: Being Python-based, Nox can be extended and understood by Python developers.
@@ -341,8 +405,8 @@ Poetry for Project Management
341405
+++++++++++++++++++++++++++++
342406

343407
While poetry was and is a good choice for Exasol project, dependency, build tool etc. "most recently"
344-
`uv <https://docs.astral.sh/uv/>`_ has surfaced and made big advanced. Looking at uv it addresses additional itches with
345-
our projects and therefore in the long run it may be a good idea to migrate our project setups to it.
408+
`uv <https://docs.astral.sh/uv/>`_ has surfaced and made big advancements. Looking at uv it addresses additional itches with
409+
our projects, and, therefore, in the long run, it may be a good idea to migrate our project setups to it.
346410
Use poetry for project, build and dependency management.
347411

348412

@@ -351,7 +415,7 @@ Code Formatting
351415

352416
**Description:**
353417

354-
Currently we use Black and Isort for code formatting, though running them on a larger code base as pre-commit hooks or such can take quite a bit of time.
418+
Currently, we use Black and Isort for code formatting, though running them on a larger code base as pre-commit hooks or such can take quite a bit of time.
355419

356420
**Downsides:**
357421

@@ -367,7 +431,7 @@ Currently we use Black and Isort for code formatting, though running them on a l
367431

368432
**Ideas/Solutions:**
369433

370-
As `Ruff <https://docs.astral.sh/ruff/>`_ is fairly stable and also tested and used by many Python projects
434+
As `Ruff <https://docs.astral.sh/ruff/>`_ is fairly stable and also tested and used by many Python projects,
371435
we should consider transitioning to it.
372436

373437
Advantages:
@@ -393,20 +457,20 @@ We are currently using Pylint instead of Ruff.
393457

394458
**Rationale/History:**
395459

396-
- Well known
460+
- Well-known
397461
- Pylint provides built-in project score/rating
398462
- Project score is good for improving legacy code bases which haven't been linted previously
399463
- Plugin support
400464

401465
**Ideas/Possible Solutions:**
402466

403-
Replacing Pylint with Ruff for linting would provide significant performance improvement. Additionally, Ruff offers an LSP and IDE integrations and is widely used these days. Additionaly there would be an additional synergy if we adopt ruff for formatting the code base.
467+
Replacing Pylint with Ruff for linting would provide significant performance improvement. Additionally, Ruff offers an LSP and IDE integrations and is widely used these days. Additionally, there would be an additional synergy if we adopt ruff for formatting the code base.
404468

405469
Transitioning to Ruff requires us to adjust the migration and improvement strategies for our projects:
406470

407471
- Currently, our codebase improvements are guided by scores. However, with Ruff, a new approach is necessary. For example, we could incrementally introduce specific linting rules, fix the related issues, and then enforce these rules.
408472

409-
- The project rating and scoring system will also need modification. One possiblity would be to run Ruff and Pylint in parallel, utilizing Pylint solely for rating and issue resolution while Ruff is incorporated for linting tasks.
473+
- The project rating and scoring system will also need modification. One possibility would be to run Ruff and Pylint in parallel, utilizing Pylint solely for rating and issue resolution while Ruff is incorporated for linting tasks.
410474

411475

412476
Security Linter

0 commit comments

Comments
 (0)