diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 46bd094..f0c436e 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -47,9 +47,10 @@ jobs:
fetch-depth: 0
- name: Set up Python
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install dependencies
run: pip install -e ".[dev]"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b5d56cc..31cc492 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -34,9 +34,10 @@ jobs:
persist-credentials: false
fetch-depth: 0
- - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- run: pip install build twine==7.0.0
@@ -67,7 +68,7 @@ jobs:
path: dist/
- name: Publish to PyPI
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
+ uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
release:
name: Create GitHub release
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 43b48c1..f30081b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -32,9 +32,10 @@ jobs:
fetch-depth: 0
- name: Set up Python
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install towncrier
run: pip install towncrier==26.9.0
@@ -52,9 +53,10 @@ jobs:
persist-credentials: false
- name: Set up Python
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install ruff
run: pip install ruff==0.16.6
@@ -75,9 +77,10 @@ jobs:
persist-credentials: false
- name: Set up Python
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install docutils
run: pip install docutils==0.22.4
@@ -103,9 +106,10 @@ jobs:
fetch-depth: 0
- name: Set up Python
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install dependencies
run: pip install -e ".[docs]"
@@ -123,9 +127,10 @@ jobs:
persist-credentials: false
- name: Set up Python
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install dependencies
run: pip install -e ".[dev]"
@@ -152,9 +157,10 @@ jobs:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: ${{ matrix.python-version }}
+ pip-version: "26.2.2"
- name: Install dependencies
run: pip install -e ".[dev]"
diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml
index 46f4835..3aec072 100644
--- a/.github/workflows/zizmor.yml
+++ b/.github/workflows/zizmor.yml
@@ -27,6 +27,11 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
+ - name: Set up Python
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
+ with:
+ python-version: "3.13"
+ pip-version: "26.2.2"
- name: Install zizmor
run: pip install zizmor==1.30.1
- name: Run zizmor
diff --git a/docs/security.rst b/docs/security.rst
index fe7eb30..2f97744 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -25,7 +25,7 @@ calendaring-jmap only corrects ``apiUrl`` when it names the same host as the ses
TLS and credentials
-------------------
-calendaring-jmap does no custom TLS handling: it relies entirely on its HTTP library (niquests, or requests as a fallback, see :ref:`dependencies`) for certificate verification, and doesn't expose an option to disable it.
+calendaring-jmap does no custom TLS handling: it relies entirely on its HTTP library (niquests, or requests as a fallback, see :ref:`dependencies`) for certificate verification, and doesn't expose an option to disable it. niquests reads trusted roots from the system's own certificate store (via `wassima `_), so keep that store current; an outdated one can keep trusting a certificate authority that's since been revoked, such as the `eMudhra emSign incident `_.
Credentials are read from explicit arguments, ``JMAP_URL``/``JMAP_USERNAME``/``JMAP_PASSWORD`` environment variables, or a YAML config file (default ``~/.config/calendaring-jmap/calendar.yaml``). The config file is stored and read as plaintext; set restrictive file permissions on it (for example, ``chmod 600``) if you use it.
diff --git a/news/72.security.rst b/news/72.security.rst
new file mode 100644
index 0000000..ba068b9
--- /dev/null
+++ b/news/72.security.rst
@@ -0,0 +1 @@
+Now requires ``wassima>=2.1.5``, which drops the compromised eMudhra emSign root certificates from its embedded fallback bundle. CI also installs pip 26.2.2 in every job and publishes to PyPI with ``gh-action-pypi-publish`` v1.14.3, both fixes for the same incident.
diff --git a/pyproject.toml b/pyproject.toml
index 3bd21a3..946892f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,6 +31,7 @@ classifiers = [
dependencies = [
"niquests>=3.21.1",
+ "wassima>=2.1.5",
"icalendar>=7.3.0",
"PyYAML>=6.0.3",
]