SEC2-049: postulo-imap locks pyjwt 2.13.0, urllib3 2.7.0 and django 6.1.1, carrying 22 published advisories, and CI never audits the lock #24

Closed
opened 2026-10-17 10:39:30 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-10-16 in a read-only security review of postulo-imap at 1375eb3, checked by a second, independent pass.

Severity: Low · Category: Dependencies · Reference: CWE-1104 (Use of Unmaintained Third Party Components); OWASP A06:2021 (Vulnerable and Outdated Components)

Location:

  • uv.lock (pyjwt 2.13.0, urllib3 2.7.0, oauthlib 3.3.1, django 6.1.1, django-allauth 65.19.2)
  • pyproject.toml:53 (postulo @ git+...@925e3e9cd35a97617cc45b36ecdde862d04515b1)
  • .forgejo/workflows/ci.yml:47-48,55 and .forgejo/workflows/release.yml:40,44 (unversioned installer; uv sync --locked; no audit step)

Issue

A pip-audit 2.10.1 run on 2026-10-16 against the exported lock reports pyjwt 2.13.0 with fourteen advisories (fixed in 2.14.0 / 2.15.0, including HMAC key-handling flaws that allow token forgery), urllib3 2.7.0 with three (fixed in 2.8.0) and oauthlib 3.3.1 with one (fixed in 4.0.0). The lock also holds django 6.1.1, whose four security fixes in 6.1.2 pip-audit cannot see (postulo/postulo SEC2-044), and django-allauth 65.19.2. The core pin (925e3e9cd, five days and 210 commits behind the core's 56fc9d531) is not the cause: the plugin's own lock has never been re-resolved, and the core's lock does not constrain it.

The plugin's own dependency is imapclient>=3.0 (pyproject.toml:21), which talks IMAP over the standard library and the destination guard, so pyjwt and urllib3 are reached only through allauth's OpenID Connect in the test environment; in production the core's constraint file decides. No audit step exists in either workflow.

Impact

The plugin's tests and every developer environment run with a JWT library that accepts forged tokens under some HMAC configurations and an HTTP stack with open advisories, and nothing in CI would say so. If the lock is ever shipped, the stale pins ship with it.

Fix

uv lock --upgrade (upgrading allauth brings oauthlib 4), re-pin the core to current main at the same time, and add the core's pip-audit step and the checksummed installer to ci.yml and release.yml. Done when: pip-audit against the exported lock reports nothing and the CI workflow fails on a new advisory.

#14 (open) - the unversioned installer and the single Python tested; it does not mention the audit or the lock's advisories. postulo/postulo-apprise#13 (open) - names this repository's installer line and missing audit among the five others. #1 (closed) - "fix CI, pins" of 2026-09-15, about the CI not running at all. postulo/postulo-dav SEC2-048 - the same lock problem in the DAV plugin.

Found on 2026-10-16 in a read-only security review of `postulo-imap` at `1375eb3`, checked by a second, independent pass. **Severity:** Low · **Category:** Dependencies · **Reference:** CWE-1104 (Use of Unmaintained Third Party Components); OWASP A06:2021 (Vulnerable and Outdated Components) **Location:** - `uv.lock` (`pyjwt 2.13.0`, `urllib3 2.7.0`, `oauthlib 3.3.1`, `django 6.1.1`, `django-allauth 65.19.2`) - `pyproject.toml:53` (`postulo @ git+...@925e3e9cd35a97617cc45b36ecdde862d04515b1`) - `.forgejo/workflows/ci.yml:47-48,55` and `.forgejo/workflows/release.yml:40,44` (unversioned installer; `uv sync --locked`; no audit step) ## Issue A pip-audit 2.10.1 run on 2026-10-16 against the exported lock reports `pyjwt 2.13.0` with fourteen advisories (fixed in 2.14.0 / 2.15.0, including HMAC key-handling flaws that allow token forgery), `urllib3 2.7.0` with three (fixed in 2.8.0) and `oauthlib 3.3.1` with one (fixed in 4.0.0). The lock also holds `django 6.1.1`, whose four security fixes in 6.1.2 pip-audit cannot see (postulo/postulo SEC2-044), and `django-allauth 65.19.2`. The core pin (`925e3e9cd`, five days and 210 commits behind the core's `56fc9d531`) is not the cause: the plugin's own lock has never been re-resolved, and the core's lock does not constrain it. The plugin's own dependency is `imapclient>=3.0` (`pyproject.toml:21`), which talks IMAP over the standard library and the destination guard, so pyjwt and urllib3 are reached only through allauth's OpenID Connect in the test environment; in production the core's constraint file decides. No audit step exists in either workflow. ## Impact The plugin's tests and every developer environment run with a JWT library that accepts forged tokens under some HMAC configurations and an HTTP stack with open advisories, and nothing in CI would say so. If the lock is ever shipped, the stale pins ship with it. ## Fix `uv lock --upgrade` (upgrading allauth brings oauthlib 4), re-pin the core to current `main` at the same time, and add the core's `pip-audit` step and the checksummed installer to `ci.yml` and `release.yml`. Done when: pip-audit against the exported lock reports nothing and the CI workflow fails on a new advisory. ## Related #14 (open) - the unversioned installer and the single Python tested; it does not mention the audit or the lock's advisories. postulo/postulo-apprise#13 (open) - names this repository's installer line and missing audit among the five others. #1 (closed) - "fix CI, pins" of 2026-09-15, about the CI not running at all. postulo/postulo-dav SEC2-048 - the same lock problem in the DAV plugin.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo-imap#24
No description provided.