Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/tox-dev/pyproject-fmt
rev: 3632ea90e7641b574983ddf3a11ccedefff3c881 # frozen: v2.25.3
rev: d600c142bb19f521ae6a6a345f94a2efd7937759 # frozen: v2.26.0
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: 4b2e70d08cb2ccd26d1fba73588de41c7a5d50b7 # frozen: v0.25
hooks:
- id: validate-pyproject
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 01a675ea018f2fb714478a5ffb83fcea8374bb06 # frozen: v0.15.21
rev: 39d9ac5938dadb73df0564a45f163e25ff9fa6e2 # frozen: v0.16.1
hooks:
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
Expand All @@ -43,14 +43,14 @@ repos:
- id: sphinx-lint
types: [rst]
- repo: https://github.com/adamchainz/blacken-docs
rev: fda77690955e9b63c6687d8806bafd56a526e45f # frozen: 1.20.0
rev: dda8db18cfc68df532abf33b185ecd12d5b7b326 # frozen: 1.20.0
hooks:
- id: blacken-docs
args: [--line-length=79]
additional_dependencies:
- black
- repo: https://github.com/codespell-project/codespell
rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a # frozen: v2.4.2
rev: 57b21406f092110c18776e39b0bda50d37c945c8 # frozen: v2.4.3
hooks:
- id: codespell
args: [--toml pyproject.toml]
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Added
Changed
~~~~~~~

* 📝 Extend seccurity section
* 👷🔧📝 Switch to prek

* Remove pre-commit
Expand Down
4 changes: 2 additions & 2 deletions docs/productive/qa/pysa.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ Ursprung zu ihrem Endpunkt und identifiziert dabei anfälligen Code.
.. seealso::
* `What Is Taint Analysis and Why Should I Care?
<https://dzone.com/articles/what-is-taint-analysis-and-why-should-i-care>`_
* `How Pysa works <https://pyre-check.org/docs/pysa-basics>`_
* `How Pysa works <https://pyre-check.org/docs/pysa-basics/>`_
* `Running Pysa <https://pyre-check.org/docs/pysa-running/>`_
* `Pysa Tutorial
<https://github.com/facebook/pyre-check/tree/main/documentation/pysa_tutorial>`_
<https://github.com/facebook/Pysa/tree/main/documentation/pysa_tutorial>`_

Konfiguration
-------------
Expand Down
675 changes: 363 additions & 312 deletions docs/productive/security/dependencies.rst

Large diffs are not rendered by default.

28 changes: 17 additions & 11 deletions docs/productive/security/environments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ die Entwicklungsumgebung enthält alle Abhängigkeiten.
So wie eure Python-Umgebung mit unveränderbaren Referenzen aktuell gehalten
werden sollte, sollten auch eure
:doc:`../git/advanced/hooks/checks` und GitHub Actions regelmäßig aktualisiert
werdenn.
werden.

In der :file:`.pre-commit-config.yaml` sollten die Versionen der Checks mit
ihren Hashes regelmäßig aktualisiert werden, :abbr:`z. B. (zum Beispiel)` mit:
Expand All @@ -68,19 +68,25 @@ ihren Hashes regelmäßig aktualisiert werden, :abbr:`z. B. (zum Beispiel)` mi
.. seealso::
:doc:`../git/advanced/hooks/prek`

GitHub Actions könnt ihr `pinact <https://github.com/suzuki-shunsuke/pinact>`_
verwenden, :abbr:`z. B. (zum Beispiel)` mit:
.. _pinact:

Überprüft eure GitHub-Actions
-----------------------------

Für GitHub Actions könnt ihr `pinact
<https://github.com/suzuki-shunsuke/pinact>`_ verwenden, :abbr:`z. B. (zum
Beispiel)` mit:

.. code-block:: console

$ pinact run -u --min-age 7

Überprüft eure GitHub-Actions
-----------------------------
`zizmor <https://docs.zizmor.sh>`_ ist ein Tool zur statischen Analyse, das
Sicherheitslücken in GitHub-Actions-Workflows aufspürt – darunter
Template-Injection, nicht fixierte Aktionen, übermäßige Berechtigungen, das
Offenlegen von Anmeldedaten sowie `mehr als 30 weitere Prüfregeln
<https://docs.zizmor.sh/audits/>`_. ``zizmor`` erkennt Schwachstellen wie
diejenigen, die durch :ref:`token_exfiltration` ausgenutzt wurden.

:ref:`zizmorcore` ist ein Tool zur statischen Analyse, das Sicherheitslücken in
GitHub-Actions-Workflows aufspürt – darunter Template-Injection, nicht fixierte
Aktionen, übermäßige Berechtigungen, das Offenlegen von Anmeldedaten sowie `mehr
als 30 weitere Prüfregeln <https://docs.zizmor.sh/audits/>`_. ``zizmor`` erkennt
Schwachstellen wie diejenigen, die durch :ref:`token_exfiltration` ausgenutzt
wurden.
.. seealso::
* :ref:`zizmorcore`
45 changes: 24 additions & 21 deletions docs/productive/security/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,18 @@ Phishing-Angriff per E-Mail auf PyPI-User
`PyPI Users Email Phishing Attack
<https://blog.pypi.org/posts/2025-07-28-pypi-phishing-attack/>`_

ZIP-Parser-Verwirrungsangriffe
Im August 2025 führte :term:`PyPI` Restriktionen ein, die verhindern sollen,
dass es bei Installations- und Prüfprogramme für Python-Pakete durch
unterschiedliche Implementierungen des ZIP-Parsers zu Verwechslungen kommen
kann. :term:`uv` zeigte ein anderes Entpackungsverhalten als viele
Python-basierte Installationsprogramme, die :mod:`zipfile` verwenden.
Shai-Hulud
Im November 2025 entwickelt sich ein Angriff auf das `npm
<https://www.npmjs.com/>`_-Ökosystem weiter und nutzt kompromittierte Konten
aus, um schädliche Pakete zu veröffentlichen. Diese als *Shai-Hulud*
bezeichnete Kampagne hat eine große Anzahl von JavaScript-Paketen ins Visier
genommen und Zugangsdaten abgezogen, um sich weiter zu verbreiten.
:term:`PyPI` selbst wurde zwar nicht ausgenutzt, jedoch wurden einige
PyPI-Anmeldedaten in kompromittierten Repositories offengelegt.

.. seealso::
`uv security advisory: ZIP payload obfuscation
<https://astral.sh/blog/uv-security-advisory-cve-2025-54368>`_
`PyPI and Shai-Hulud: Staying Secure Amid Emerging Threats
<https://blog.pypi.org/posts/2025-11-26-pypi-and-shai-hulud/>`_

.. _token_exfiltration:

Expand All @@ -79,6 +81,19 @@ Token Exfiltration
`Token Exfiltration Campaign via GitHub Actions Workflows
<https://blog.pypi.org/posts/2025-09-16-github-actions-token-exfiltration/>`_

ZIP-Parser-Verwirrungsangriffe
Im August 2025 führte :term:`PyPI` Restriktionen ein, die verhindern sollen,
dass es bei Installations- und Prüfprogramme für Python-Pakete durch
unterschiedliche Implementierungen des ZIP-Parsers zu Verwechslungen kommen
kann. :term:`uv` zeigte ein anderes Entpackungsverhalten als viele
Python-basierte Installationsprogramme, die :mod:`zipfile` verwenden.

.. seealso::
`uv security advisory: ZIP payload obfuscation
<https://astral.sh/blog/uv-security-advisory-cve-2025-54368>`_

.. _ultralytics:

Ultralytics
Im Dezember 2024 wurde `ultralytics
<https://pypi.org/project/ultralytics/>`_ Opfer eines Supply-Chain-Angriffs,
Expand All @@ -90,19 +105,6 @@ Ultralytics
`Supply-chain attack analysis: Ultralytics
<https://blog.pypi.org/posts/2024-12-11-ultralytics-attack-analysis/>`_

Shai-Hulud
Im November 2025 entwickelt sich ein Angriff auf das `npm
<https://www.npmjs.com/>`_-Ökosystem weiter und nutzt kompromittierte Konten
aus, um schädliche Pakete zu veröffentlichen. Diese als *Shai-Hulud*
bezeichnete Kampagne hat eine große Anzahl von JavaScript-Paketen ins Visier
genommen und Zugangsdaten abgezogen, um sich weiter zu verbreiten.
:term:`PyPI` selbst wurde zwar nicht ausgenutzt, jedoch wurden einige
PyPI-Anmeldedaten in kompromittierten Repositoriess offengelegt.

.. seealso::
`PyPI and Shai-Hulud: Staying Secure Amid Emerging Threats
<https://blog.pypi.org/posts/2025-11-26-pypi-and-shai-hulud/>`_

Das sind keine theoretischen Angriffe. Sie haben sich bei echten Projekten mit
Millionen von Nutzer*innen ereignet. Wenn ihr ein bösartiges Paket auf PyPI
entdeckt, könnt ihr es über das `Sicherheitsmeldesystem von PyPI
Expand Down Expand Up @@ -137,6 +139,7 @@ seit Juli 2024 erstellten Berichte zu GitHub-Sicherheitshinweisen:
:titlesonly:
:maxdepth: 0

own-code
dependencies
environments
sbom
165 changes: 165 additions & 0 deletions docs/productive/security/own-code.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
.. SPDX-FileCopyrightText: 2023 cusy GmbH
..
.. SPDX-License-Identifier: BSD-3-Clause

Eigener Code
============

Angriffe auf die Lieferkette gehen nicht nur von :doc:`dependencies` aus, auch
euer eigener Code kann Angriffspunkte liefern. Ein fest im Quellcode
hinterlegtes PyPI-Token liefert, sobald es in ein öffentliches Repository
hochgeladen wurde, alles, was für einem Angriff benötigt wird und euer Konto zu
kompromittieren und bösartige Pakete unter eurem Namen zu veröffentlichen.
Abgesehen von Secrets verbergen sich häufige Sicherheitsfehler in alltäglichen
Codemustern, die bei einem Code-Review zunächst unbedenklich erscheinen und von
Menschen übersehen werden können. Diese mit einem Linter aufzuspüren, ist die
erste Verteidigungsstufe.

Das ewige Geheimnis
-------------------

Durchgesickerte Zugangsdaten sind der Ausgangspunkt für viele
Sicherheitsverletzungen in der Lieferkette. Ein offengelegtes :term:`PyPI`-Token
ermöglicht, mit Hintertüren versehene Versionen eurer Pakete zu veröffentlichen.
Eine offengelegte Datenbank-URL ermöglicht, Daten zu entwenden. Und doch ist ein
solches Muster weit verbreitet. Besser ist die Verwendung von
Umgebungsvariablen:

.. code-block:: python

import os

DATABASE_KEY = os.environ["DB_KEY"]
DATABASE_URL = os.environ["DB_URL"]

.. warning::
Git vergisst nie: wenn ihr ein Secret einmal durch Git verwaltet habt, bleibt
es für immer in der Historie eures Repositories erhalten. Es in einem
späteren Commit einfach zu löschen, hilft nicht wirklich. Alle, die Zugriff
auf das Repository haben, können diese Anmeldedaten wieder extrahieren. Bei
Angriffen wird oft zunächst die Git-Historie nach Geheimnissen durchforstet,
und ein einmal veröffentlichts PyPI-Token oder Cloud-Anmeldedaten sind oft
der erste Schritt bei einer Kompromittierung der Lieferkette.

Kryptografische Schwachstellen
------------------------------

Weitere häufige Sicherheitslücken sind kryptografische Schwachstellen wie
`MD5 <https://de.wikipedia.org/wiki/Message-Digest_Algorithm_5>`_ und `SHA-1
<https://de.wikipedia.org/wiki/Secure_Hash_Algorithm#SHA-1>`_. MD5-Kollisionen
wurden erstmals 2004 nachgewiesen und SHA1-Kollisionen 2017. Es können also
Kollisionen erzeugt werden durch andere Eingaben, die denselben Hash-Wert
ergeben. Dies ermöglicht die Fälschung von Zertifikaten, die Manipulation von
Downloads oder die Umgehung von Integritätsprüfungen. Verwendet daher keines der
beiden Verfahren für Sicherheitszwecke sondern stattdessen `SHA256 oder besser
<https://de.wikipedia.org/wiki/SHA-2>`_:

.. code-block:: python

import hashlib

digest = hashlib.sha256(payload).hexdigest()

Hängende Verbindungen
---------------------

Das hier ist zwar subtil, aber dennoch gefährlich, da ein langsamer Server
euren Prozess auf unbestimmte Zeit zum Stillstand bringen kann. Ein Angriff über
einen solchen Server, mit dem eure Anwendung kommuniziert, kann jede Anfrage zum
Erliegen bringen, euren Thread-Pool erschöpfen und einen
Denial-of-Service-Angriff auslösen. Eure gesamte Anwendung kommt dann zum
Stillstand, weil ihr einen Parameter vergessen habt. Daher solltet ihr immer
einen Timeout angeben:

.. code-block:: pycon

>>> import httpx
>>> r = httpx.get("https://httpbin.org/get", timeout=30)
httpx.ReadTimeout: The read operation timed out

.. _bandit:

Erkennt Sicherheitslücken mit Ruff
----------------------------------

:doc:`../qa/ruff` ist ein schneller Python-Linter, der umfassende
Sicherheitsregeln von :ref:`Bandit <bandit>` enthält:

.. code-block:: console

$ uvx ruff check --select S .

.. seealso::
Weitere Informationen findet ihr in der `Dokumentation zu den
Ruff-Sicherheitsregeln
<https://docs.astral.sh/ruff/rules/#flake8-bandit-s>`_.

Für zukünftige Checks könnt ihr ``ruff`` ihn in der :file:`pyproject.toml`-Datei
konfigurieren:

.. code-block:: toml

[tool.ruff]
lint.select = ["S"]

Die Sicherheitsregeln ``["S"]`` mit den Bandit-Prüfungen.spüren fest codierte
Geheimnisse, schwache Verschlüsselung und unsichere Deserialisierung auf. Dabei
läuft Ruff in weniger als einer Sekunde, sodass ihr es während der Eingabe in
eurer IDE und vor jedem Commit ausführen könnt. Alle drei oben genannten
Schwachstellen werden erkannt und noch viel mehr, :abbr:`u. a. (unter anderem)`:

+--------+-----------------------------------------------------------------------+
| Regel | Beschreibung |
+--------+-----------------------------------------------------------------------+
| `S105`_| fest codierte Geheimnisse |
+--------+-----------------------------------------------------------------------+
| `S301`_| :doc:`/data-processing/serialisation-formats/pickle/index` und andere |
| | unsichere Deserialisierung |
+--------+-----------------------------------------------------------------------+
| `S307`_| Verwendung von :func:`eval` mit nicht vertrauenswürdigen Eingaben |
+--------+-----------------------------------------------------------------------+
| `S113`_| fehlende Zeitüberschreitungen |
+--------+-----------------------------------------------------------------------+
| `S324`_| schwache Kryptografie wie :abbr:`z. B. (zum Beispiel)` MD5-Kollisionen|
+--------+-----------------------------------------------------------------------+
| `S608`_| SQL-Injection über String-Formatierung |
+--------+-----------------------------------------------------------------------+

.. seealso::
* `flake8-bandit (S) <https://docs.astral.sh/ruff/rules/#flake8-bandit-s>`_
* `lint.flake8-bandit
<https://docs.astral.sh/ruff/settings/#lintflake8-bandit>`_

Bandit könnt ihr auch in Jupyter Notebooks, :abbr:`IDEs (Integrated Development
Wnvironments)` und :doc:`../git/advanced/hooks/prek` integrieren.

Zudem könnt ihr :doc:`../qa/pysa` für `Taint
<https://en.wikipedia.org/wiki/Taint_checking>`_-Analysen verwenden.

Für GitHub-Repositories könnt ihr alternativ auch `CodeQL
<https://codeql.github.com>`_ verwenden; :abbr:`s.a. (siehe auch)`
`codeql-action
<https://github.com/github/codeql-action/blob/main/README.md#usage>`_.

Vertrauenswürdige Veröffentlichung
----------------------------------

In einem früheren Abschnitt haben wir schon einige Hinweise gegeben, wie die
Veröffentlichung von Python-Paketen auf :term:`PyPI` abgesichert werden kann:

.. seealso::
* :ref:`secure-release-workflow`
* :ref:`add_2fa`

.. seealso::
* `Publishing package distribution releases using GitHub Actions CI/CD
workflows
<https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/>`_

.. _S105: https://docs.astral.sh/ruff/rules/hardcoded-password-string/
.. _S301: https://docs.astral.sh/ruff/rules/suspicious-pickle-usage/
.. _S307: https://docs.astral.sh/ruff/rules/suspicious-eval-usage/
.. _S113: https://docs.astral.sh/ruff/rules/request-without-timeout/
.. _S324: https://docs.astral.sh/ruff/rules/hashlib-insecure-hash-function/
.. _S608: https://docs.astral.sh/ruff/rules/hardcoded-sql-expression/
.. _S608: https://docs.astral.sh/ruff/rules/hardcoded-sql-expression/
Binary file added docs/productive/security/pypi-changes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions docs/productive/security/sbom.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,22 @@ Eine Software Bill-of-Materials (SBOM) ist ein Dokument zum Austausch von
Informationen über Software und deren Zusammensetzung. Dieses Format wird vor
allem im Sicherheitsbereich verwendet, um Software und ihre Abhängigkeiten
mithilfe von Schwachstellendatenbanken wie `CVE <https://www.cve.org/>`_ und
`OSV <https://osv.dev/>`_ auf Schwachstellen zu überprüfen. Das vom
CPython-Projekt verwendete SBOM-Format ist `SPDX
`OSV <https://osv.dev/>`_ auf Schwachstellen zu überprüfen.

Das vom CPython-Projekt verwendete SBOM-Format ist `SPDX
<https://spdx.github.io/spdx-spec/v3.0.1/model/Software/Classes/Sbom/>`_, das
bei Bedarf in andere Formate konvertiert werden kann. Die SBOM-Datei für die in
CPython enthaltenen Abhängigkeiten wird unter `Misc/sbom.spdx.json
<https://github.com/python/cpython/blob/main/Misc/sbom.spdx.json>`_ verwaltet.
Die Datei wird erstellt mit `Tools/build/generate_sbom.py
<https://github.com/python/cpython/blob/main/Tools/build/generate_sbom.py>`_.
Ihr könnt die SBOM-Datei für jede Python-Version abrufen unter
:samp:`https://www.python.org/ftp/python/{MAJOR.MINOR.PATCH}/Python-{MAJOR.MINOR.PATCH}.tgz.spdx.json`, also :abbr:`z.B. (zum Beispiel)` unter
https://www.python.org/ftp/python/3.14.6/Python-3.14.6.tgz.spdx.json.

.. seealso::
* `Python Software Bill-of-Materials Information
<https://www.python.org/downloads/metadata/sbom/>`_

SBOM-Datei erstellen
--------------------
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ packages = []
line-length = 79
src = [ "docs", "fastAPI" ]
extend-exclude = [
"docs/productive/qa/requests/*",
"docs/workspace/ipython/examples.ipynb", # `np.*mean*?` is valid iPython syntax
"docs/data-processing/apis/grpc/accounts_pb2_grpc.py", # Changing the function signature would violate the Liskov Substitution Principle
"docs/productive/qa/requests/*",
"docs/workspace/ipython/examples.ipynb", # `np.*mean*?` is valid iPython syntax
]
lint.select = [ "ALL" ]
lint.ignore = [
Expand Down
Loading