Bump httpx2 to 2.12 to resolve four HTTP stack security advisories #34

Manually merged
marvin8 merged 9 commits from fix/issue-33-bump-httpx2-security into main 2026-09-13 19:51:24 +00:00
Collaborator

The weekly pysentry audit reported 2 HIGH and 2 MEDIUM findings against the HTTP stack. This PR bumps the direct dependency httpx2 from ~=2.3 to ~=2.12 and adds an explicit floor for the transitive httpcore2.

Advisories resolved

  • PYSEC-2026-3844 (HIGH 8.1) — httpcore2: wss:// traffic sent plaintext through SOCKS proxies
  • PYSEC-2026-3846 (HIGH 7.5) — httpx2: unbounded decompression amplification on streaming responses
  • PYSEC-2026-3848 (MED 5.3) — httpx2: multipart part header injection via unvalidated file Content-Type/headers
  • PYSEC-2026-3849 (MED) — httpx2: auto-generated Content-Length alongside caller Transfer-Encoding (request smuggling)

Notes

  • httpx2 2.12.0 pins its httpcore2 dependency exactly — Requires-Dist: httpcore2==2.12.0, verified from the published wheel metadata — so a correct install of httpx2 2.12.0 cannot pair with any other httpcore2, and downstream installs are protected by that pin alone. The deliberate httpcore2>=2.12.0 entry in [tool.uv] constraint-dependencies (0288996) remains as defence-in-depth: it enforces the floor for longwei's own builds and guards against a future httpx2 2.x release relaxing the pin. It is a uv-only setting and does not propagate to downstream resolvers — nor does it need to.
  • pylock.toml regenerated (resolved versions unchanged by the floor, so its diff is empty from 0288996); Release-Notes.md updated — security fixes are user-facing.

Verification

  • 0288996 CI run 596, 6200129 run 600, and subsequent heads: ruff, ty, interrogate, complexipy, pysentry (0 vulnerabilities; sources pinned to osv,pypi per 6200129 to stop the PyPA-fetch flake, #35), pytest on 3.11/3.12/3.13/3.14/3.14t, deptry, dependency_versions — all green, including uv sync --locked consistency.

Closes #33

The weekly pysentry audit reported 2 HIGH and 2 MEDIUM findings against the HTTP stack. This PR bumps the direct dependency `httpx2` from `~=2.3` to `~=2.12` and adds an explicit floor for the transitive `httpcore2`. **Advisories resolved** - PYSEC-2026-3844 (HIGH 8.1) — httpcore2: `wss://` traffic sent plaintext through SOCKS proxies - PYSEC-2026-3846 (HIGH 7.5) — httpx2: unbounded decompression amplification on streaming responses - PYSEC-2026-3848 (MED 5.3) — httpx2: multipart part header injection via unvalidated file Content-Type/headers - PYSEC-2026-3849 (MED) — httpx2: auto-generated Content-Length alongside caller Transfer-Encoding (request smuggling) **Notes** - httpx2 2.12.0 pins its httpcore2 dependency exactly — `Requires-Dist: httpcore2==2.12.0`, verified from the published wheel metadata — so a correct install of httpx2 2.12.0 cannot pair with any other httpcore2, and downstream installs are protected by that pin alone. The deliberate `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` (`0288996`) remains as defence-in-depth: it enforces the floor for longwei's own builds and guards against a future httpx2 2.x release relaxing the pin. It is a uv-only setting and does not propagate to downstream resolvers — nor does it need to. - `pylock.toml` regenerated (resolved versions unchanged by the floor, so its diff is empty from `0288996`); `Release-Notes.md` updated — security fixes are user-facing. **Verification** - `0288996` CI run 596, `6200129` run 600, and subsequent heads: ruff, ty, interrogate, complexipy, pysentry (0 vulnerabilities; sources pinned to osv,pypi per `6200129` to stop the PyPA-fetch flake, #35), pytest on 3.11/3.12/3.13/3.14/3.14t, deptry, dependency_versions — all green, including `uv sync --locked` consistency. Closes #33
⬆️ bump: httpx2 to ~=2.12 to address PYSEC-2026-3844/3846/3848/3849
Some checks failed
/ gitleaks (pull_request) Successful in 12s
/ pr-review (pull_request) Successful in 1m10s
/ checks (pull_request) Failing after 11m43s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
3789294d70
httpx2 2.12.0 also pulls in httpcore2 2.12.0, clearing the SOCKS/wss
plaintext advisory without a separate constraint-dependencies entry.
Regenerated pylock.toml and updated Release-Notes.md.

Closes #33
forgejo-actions left a comment

WuMing

Found 5 issue(s). See inline comments below.

## WuMing Found **5** issue(s). See inline comments below.
Release-Notes.md Outdated
@ -10,3 +11,4 @@
---
Four security advisories were published against the httpx2 version longwei depends on. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei itself never uses SOCKS proxies, WebSockets, or raw multipart tuples, but any application fetching compressed responses through the old version was exposed to the memory-amplification issue.

docs [MEDIUM]

This paragraph attributes all four advisories to httpx2 ("published against the httpx2 version longwei depends on"), but the advisory described in the very next sentence as "the most serious" — PYSEC-2026-3844 (httpcore2: wss:// plaintext through SOCKS proxies) — is an httpcore2 advisory, not an httpx2 one. A reader who cross-checks the PYSEC database will find the note inaccurate. Fix: say the advisories were published against "httpx2 and its httpcore2 dependency" (or against "the HTTP stack") rather than against httpx2 alone.

**docs** [MEDIUM] This paragraph attributes all four advisories to httpx2 ("published against the httpx2 version longwei depends on"), but the advisory described in the very next sentence as "the most serious" — PYSEC-2026-3844 (httpcore2: wss:// plaintext through SOCKS proxies) — is an httpcore2 advisory, not an httpx2 one. A reader who cross-checks the PYSEC database will find the note inaccurate. Fix: say the advisories were published against "httpx2 and its httpcore2 dependency" (or against "the HTTP stack") rather than against httpx2 alone. <!-- wuming:sha256:664d3f6938e2205ee1a413beea7aba0d3c0385d22a28cb394fe22cc00f918a07 -->

docs [LOW]

The absolute claim that "longwei itself never uses SOCKS proxies, WebSockets, or raw multipart tuples" is not substantiated anywhere in the PR description or diff, and it is materially reassuring to users of a security note. If longwei ever passes open file objects/tuples to httpx2 for multipart uploads (plausible for ActivityPub media uploads), this statement is wrong. Fix: verify the claim against the codebase and cite it, or soften to describe the actual exposure (e.g. "longwei's supported configuration does not use SOCKS proxies or WebSockets").

**docs** [LOW] The absolute claim that "longwei itself never uses SOCKS proxies, WebSockets, or raw multipart tuples" is not substantiated anywhere in the PR description or diff, and it is materially reassuring to users of a security note. If longwei ever passes open file objects/tuples to httpx2 for multipart uploads (plausible for ActivityPub media uploads), this statement is wrong. Fix: verify the claim against the codebase and cite it, or soften to describe the actual exposure (e.g. "longwei's supported configuration does not use SOCKS proxies or WebSockets"). <!-- wuming:sha256:664d3f6938e2205ee1a413beea7aba0d3c0385d22a28cb394fe22cc00f918a07 -->
Release-Notes.md Outdated
@ -12,1 +13,4 @@
Four security advisories were published against the httpx2 version longwei depends on. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei itself never uses SOCKS proxies, WebSockets, or raw multipart tuples, but any application fetching compressed responses through the old version was exposed to the memory-amplification issue.
The pinned dependency is now httpx2 2.12, which also pulls in the patched httpcore2 — all four advisories are resolved with no API changes to longwei, and the full test suite passes unchanged.

docs [MEDIUM]

"which also pulls in the patched httpcore2" overstates the guarantee. Per the PR notes, httpx2 2.12.0 declares httpcore2 with no version floor, so upgrading httpx2 does not itself force the patched httpcore2 — the guarantee comes from the committed uv.lock/pylock.toml. Users who upgrade with the install command below (pip install longwei) resolve httpcore2 separately and could get an unpatched version. Fix: attribute the fix to the lockfile (e.g. "the committed lockfile pins httpcore2 2.12.0, which resolves the httpcore2 advisory") and mention the constraint-dependency fallback if the audit flags httpcore2 again.

**docs** [MEDIUM] "which also pulls in the patched httpcore2" overstates the guarantee. Per the PR notes, httpx2 2.12.0 declares httpcore2 with no version floor, so upgrading httpx2 does not itself force the patched httpcore2 — the guarantee comes from the committed uv.lock/pylock.toml. Users who upgrade with the install command below (pip install longwei) resolve httpcore2 separately and could get an unpatched version. Fix: attribute the fix to the lockfile (e.g. "the committed lockfile pins httpcore2 2.12.0, which resolves the httpcore2 advisory") and mention the constraint-dependency fallback if the audit flags httpcore2 again. <!-- wuming:sha256:ff8607c97f07a92345710ef06c824065575f55b11faff9d66c1c81049211fd56 -->
@ -25,3 +25,3 @@
requires-python = ">=3.11"
dependencies = [
"httpx2[http2]~=2.3",
"httpx2[http2]~=2.12",

config [HIGH]

Only the direct dependency is bumped, but one of the two HIGH advisories (PYSEC-2026-3844) is against the transitive package httpcore2. The PR notes concede that httpx2 2.12.0's metadata declares httpcore2 with no version floor, so nothing in pyproject.toml prevents the resolver from re-selecting a vulnerable httpcore2 (2.3.0) on the next uv lock / in a fresh environment — the entire mitigation rests on the committed lock, and this diff shows no uv.lock hunks at all, so it is not even clear the guarantee the PR relies on was regenerated. Add an explicit floor, e.g. [tool.uv] constraint-dependencies = ["httpcore2>=2.12.0"] (or declare httpcore2 as a direct dependency), and regenerate both uv.lock and pylock.toml so the patched HTTP stack is enforced by declared constraints rather than by lockfile state alone.

**config** [HIGH] Only the direct dependency is bumped, but one of the two HIGH advisories (PYSEC-2026-3844) is against the transitive package httpcore2. The PR notes concede that httpx2 2.12.0's metadata declares httpcore2 with no version floor, so nothing in pyproject.toml prevents the resolver from re-selecting a vulnerable httpcore2 (2.3.0) on the next `uv lock` / in a fresh environment — the entire mitigation rests on the committed lock, and this diff shows no uv.lock hunks at all, so it is not even clear the guarantee the PR relies on was regenerated. Add an explicit floor, e.g. `[tool.uv] constraint-dependencies = ["httpcore2>=2.12.0"]` (or declare httpcore2 as a direct dependency), and regenerate both uv.lock and pylock.toml so the patched HTTP stack is enforced by declared constraints rather than by lockfile state alone. <!-- wuming:sha256:795511027509fc53a4d3ffc48a340703e2a9c8a9ccf09ffd157f38ecded6d752 -->

security [MEDIUM]

A06: The direct dependency httpx2[http2]~=2.12 does not enforce a secure floor for the transitive httpcore2 dependency. As noted, httpx2 2.12.0 metadata declares httpcore2 without a version floor, so non-lock installs from pyproject may still select the vulnerable httpcore2 2.3.0 affected by PYSEC-2026-3844. Add an explicit constraint such as httpcore2>=2.12 to ensure the fixed version is required.

**security** [MEDIUM] A06: The direct dependency `httpx2[http2]~=2.12` does not enforce a secure floor for the transitive `httpcore2` dependency. As noted, httpx2 2.12.0 metadata declares httpcore2 without a version floor, so non-lock installs from pyproject may still select the vulnerable httpcore2 2.3.0 affected by PYSEC-2026-3844. Add an explicit constraint such as `httpcore2>=2.12` to ensure the fixed version is required. <!-- wuming:sha256:795511027509fc53a4d3ffc48a340703e2a9c8a9ccf09ffd157f38ecded6d752 -->
marvin8 marked this conversation as resolved
🔧 constrain httpcore2>=2.12.0 for PYSEC-2026-3844 and reword release notes
All checks were successful
/ gitleaks (pull_request) Successful in 22s
/ pr-review (pull_request) Successful in 35s
/ checks (pull_request) Successful in 3m32s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
02889960e9
Addresses the WuMing wave on PR #34: explicit floor for the transitive
httpcore2 dependency (matching house constraint-dependencies convention),
release-notes attribution corrected (httpcore2 advisory, lockfile-based
guarantee), and the no-SOCKS/WS/multipart claim grounded in a source search.
Author
Collaborator

Fixed — all five findings addressed in commit 0288996

pyproject.toml

config [HIGH]

Added "httpcore2>=2.12.0", # PYSEC-2026-3844 to [tool.uv] constraint-dependencies (alphabetically sorted, house convention). uv.lock and pylock.toml regenerated in the same commit so the floor is enforced by declared constraints, not lockfile state alone.


pyproject.toml

security [MEDIUM]

Same finding as 3042 (identical wuming:sha256) — covered by the same constraint in commit 0288996.


Release-Notes.md

docs [MEDIUM]

Reworded in commit 0288996: the notes now attribute the guarantee to the explicit httpcore2>=2.12 floor plus the committed lockfiles, and tell downstream pip install longwei users that their resolver picks httpx2/httpcore2 independently (advise 2.12+ on both).


Release-Notes.md

docs [MEDIUM]

Reworded in commit 0288996: "published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency".


Release-Notes.md

docs [LOW]

Softened and grounded in commit 0288996: the claim is now scoped to what a search of the library source confirms — no SOCKS proxy, WebSocket, or multipart file-tuple usage — with the decompression-amplification exposure called out separately.

### ✅ Fixed — all five findings addressed in commit `0288996` [`pyproject.toml`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3042) > **config** [HIGH] ✅ Added `"httpcore2>=2.12.0", # PYSEC-2026-3844` to `[tool.uv] constraint-dependencies` (alphabetically sorted, house convention). `uv.lock` and `pylock.toml` regenerated in the same commit so the floor is enforced by declared constraints, not lockfile state alone. --- [`pyproject.toml`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3046) > **security** [MEDIUM] ✅ Same finding as [3042](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3042) (identical wuming:sha256) — covered by the same constraint in commit `0288996`. --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3044) > **docs** [MEDIUM] ✅ Reworded in commit `0288996`: the notes now attribute the guarantee to the explicit `httpcore2>=2.12` floor plus the committed lockfiles, and tell downstream `pip install longwei` users that their resolver picks httpx2/httpcore2 independently (advise 2.12+ on both). --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3043) > **docs** [MEDIUM] ✅ Reworded in commit `0288996`: "published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency". --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3045) > **docs** [LOW] ✅ Softened and grounded in commit `0288996`: the claim is now scoped to what a search of the library source confirms — no SOCKS proxy, WebSocket, or multipart file-tuple usage — with the decompression-amplification exposure called out separately.
forgejo-actions left a comment

WuMing

Found 4 issue(s). See inline comments below.

## WuMing Found **4** issue(s). See inline comments below.
Release-Notes.md Outdated
@ -5,11 +5,18 @@ visibility: public
longwei 2.1.2
- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf
- **Security:** httpx2 pinned to 2.12+ with an explicit httpcore2>=2.12 floor, clearing four advisories in the HTTP stack (PYSEC-2026-3844/3846/3848/3849)

docs [HIGH]

This release note claims an "explicit httpcore2>=2.12 floor", but the PR description explicitly states that no constraint-dependencies entry was needed because httpx2 2.12.0 pulls httpcore2 up on its own, and no dependency-manifest change (e.g. pyproject.toml) appears in this diff. Publishing a security note that asserts a dependency floor longwei does not actually enforce is misleading. Either add the floor to the dependency manifest so the statement is true, or reword to describe what actually protects users (the committed uv.lock resolving httpcore2 to 2.12.0) and drop the reference to an explicit floor.

**docs** [HIGH] This release note claims an "explicit httpcore2>=2.12 floor", but the PR description explicitly states that no `constraint-dependencies` entry was needed because httpx2 2.12.0 pulls httpcore2 up on its own, and no dependency-manifest change (e.g. pyproject.toml) appears in this diff. Publishing a security note that asserts a dependency floor longwei does not actually enforce is misleading. Either add the floor to the dependency manifest so the statement is true, or reword to describe what actually protects users (the committed `uv.lock` resolving httpcore2 to 2.12.0) and drop the reference to an explicit floor. <!-- wuming:sha256:831267d93d3905fcc14d15fd24d112deaa2acc3a7c0058888a0afad4077bcaa6 -->
Release-Notes.md Outdated
@ -12,1 +13,4 @@
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei's own code has no SOCKS proxy, WebSocket, or multipart file-tuple usage (a search of the library source confirms this), but any application fetching compressed responses through the old httpx2 was exposed to the memory-amplification issue.
longwei now pins httpx2 ~=2.12 and enforces an explicit httpcore2>=2.12 floor, and the committed lockfiles resolve both to the patched 2.12.0 releases. If you install longwei into your own project, your resolver picks httpx2 and httpcore2 from PyPI independently — make sure your environment resolves httpx2 2.12+ and httpcore2 2.12+. No API changes to longwei, and the full test suite passes unchanged.

docs [HIGH]

Same unsupported claim repeated in the body: "enforces an explicit httpcore2>=2.12 floor". Per the PR description, httpx2 2.12.0 declares httpcore2 without a version floor, so nothing in this change enforces httpcore2>=2.12 for downstream installers. The paragraph then correctly tells readers their resolver picks httpcore2 independently — which contradicts the "enforces" wording. Rewrite to say longwei pins httpx2 ~=2.12 and that the lockfiles resolve httpcore2 to 2.12.0, while downstream users must ensure their own resolver does the same.

**docs** [HIGH] Same unsupported claim repeated in the body: "enforces an explicit httpcore2>=2.12 floor". Per the PR description, httpx2 2.12.0 declares httpcore2 without a version floor, so nothing in this change enforces httpcore2>=2.12 for downstream installers. The paragraph then correctly tells readers their resolver picks httpcore2 independently — which contradicts the "enforces" wording. Rewrite to say longwei pins httpx2 ~=2.12 and that the lockfiles resolve httpcore2 to 2.12.0, while downstream users must ensure their own resolver does the same. <!-- wuming:sha256:e551be5ef26e3e6e0a92cdfc81551b837bce17f940eddc258324890ef21d0310 -->
@ -25,3 +25,3 @@
requires-python = ">=3.11"
dependencies = [
"httpx2[http2]~=2.3",
"httpx2[http2]~=2.12",

config [MEDIUM]

The PR notes rely on the committed uv.lock as the actual guarantee that httpcore2 stays at the patched version ("httpx2 2.12.0 metadata declares httpcore2 without a version floor"), but the diff only contains the --- a/uv.lock header with no pin changes shown. If uv.lock was not regenerated alongside pyproject.toml, uv sync --locked / CI installs will fail on the unsatisfied httpx2[http2]~=2.12 requirement, or the audited environment may still resolve the vulnerable 2.3.0. Regenerate and commit uv.lock in this change and confirm it pins httpx2 2.12.0 and httpcore2 2.12.0.

**config** [MEDIUM] The PR notes rely on the committed uv.lock as the actual guarantee that httpcore2 stays at the patched version ("httpx2 2.12.0 metadata declares httpcore2 without a version floor"), but the diff only contains the `--- a/uv.lock` header with no pin changes shown. If uv.lock was not regenerated alongside pyproject.toml, `uv sync --locked` / CI installs will fail on the unsatisfied `httpx2[http2]~=2.12` requirement, or the audited environment may still resolve the vulnerable 2.3.0. Regenerate and commit uv.lock in this change and confirm it pins httpx2 2.12.0 and httpcore2 2.12.0. <!-- wuming:sha256:823b5c9c3afa3234fa5470725a3c4f0b80fcf055a7c15b21c78b5b0c8cb8ec90 -->
marvin8 marked this conversation as resolved
@ -51,6 +51,7 @@ dev = [
constraint-dependencies = [
"click>=8.3.3", # PYSEC-2026-2132
"h2>=4.4.1", # GHSA-6hr6-w5qg-qmwg
"httpcore2>=2.12.0", # PYSEC-2026-3844

config [LOW]

The PR description explicitly states "no constraint-dependencies entry was needed" because httpx2 2.12.0 pulls httpcore2 2.12.0 in transitively, yet this line adds exactly such a constraint. Pick one story: either the constraint is required (httpx2's metadata declares httpcore2 with no version floor, as the notes say) and the PR text should be corrected to say the floor was added deliberately as a durable guard, or it is redundant and should be dropped so the lockfile remains the single source of truth. Leaving the code and the description in disagreement makes the security guarantee ambiguous.

**config** [LOW] The PR description explicitly states "no `constraint-dependencies` entry was needed" because httpx2 2.12.0 pulls httpcore2 2.12.0 in transitively, yet this line adds exactly such a constraint. Pick one story: either the constraint is required (httpx2's metadata declares httpcore2 with no version floor, as the notes say) and the PR text should be corrected to say the floor was added deliberately as a durable guard, or it is redundant and should be dropped so the lockfile remains the single source of truth. Leaving the code and the description in disagreement makes the security guarantee ambiguous. <!-- wuming:sha256:6c0a484ed28db35515d2de673748205741b142dc44047d63a52c9396daba234e -->
marvin8 marked this conversation as resolved
📝 scope the httpcore2 floor claim to longwei's own build
Some checks failed
/ gitleaks (pull_request) Successful in 24s
/ pr-review (pull_request) Successful in 1m21s
/ checks (pull_request) Failing after 11m53s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
aec2334c1b
Wave-2 review on PR #34: 'enforces an explicit httpcore2>=2.12 floor'
overstated the guarantee for downstream installers — the constraint lives
in longwei's dependency configuration and lockfiles, not in what a pip
install of longwei sees. Reworded accordingly.
Author
Collaborator

Wave 2 — 2 actioned, 1 declined with evidence, 1 resolved by PR-body update

pyproject.toml

config [LOW]

PR description corrected — it now states the httpcore2>=2.12.0 floor was added deliberately in 0288996 as a durable guard (httpx2's metadata has no version floor on httpcore2), no longer claiming "no constraint needed".


pyproject.toml

config [MEDIUM]

🔴 Declined with evidence — the premise no longer holds on the current head. Commit 0288996 does modify uv.lock; the hunk is:

 constraints = [
     { name = "click", specifier = ">=8.3.3" },
     { name = "h2", specifier = ">=4.4.1" },
+    { name = "httpcore2", specifier = ">=2.12.0" },

near the top of the file, which may be why a truncated diff view showed only the header. uv sync --locked succeeded in CI run 596 on that commit, proving lock/pyproject consistency, and the lock resolves httpcore2 to 2.12.0. pylock.toml was also regenerated (uv export) — its output was byte-identical because the floor changes no resolved versions and the pylock format carries no constraint metadata, hence no diff hunk.


Release-Notes.md

docs [HIGH]

Reworded in commit aec2334 — the sentence now scopes the floor to longwei's own build ("enforced by an explicit httpcore2>=2.12 constraint in the project's dependency configuration and recorded in the committed lockfiles") and leaves downstream guidance standalone.


Release-Notes.md

docs [HIGH]

Same paragraph as 3054 — fixed by the same reword in aec2334. The floor does exist in pyproject.toml as of 0288996; the note no longer describes it as something downstream installs inherit.

### Wave 2 — 2 actioned, 1 declined with evidence, 1 resolved by PR-body update [`pyproject.toml`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3051) > **config** [LOW] ✅ PR description corrected — it now states the `httpcore2>=2.12.0` floor was added deliberately in `0288996` as a durable guard (httpx2's metadata has no version floor on httpcore2), no longer claiming "no constraint needed". --- [`pyproject.toml`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3052) > **config** [MEDIUM] 🔴 Declined with evidence — the premise no longer holds on the current head. Commit `0288996` does modify `uv.lock`; the hunk is: ```diff constraints = [ { name = "click", specifier = ">=8.3.3" }, { name = "h2", specifier = ">=4.4.1" }, + { name = "httpcore2", specifier = ">=2.12.0" }, ``` near the top of the file, which may be why a truncated diff view showed only the header. `uv sync --locked` succeeded in CI run 596 on that commit, proving lock/pyproject consistency, and the lock resolves httpcore2 to 2.12.0. `pylock.toml` was also regenerated (`uv export`) — its output was byte-identical because the floor changes no resolved versions and the pylock format carries no constraint metadata, hence no diff hunk. --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3054) > **docs** [HIGH] ✅ Reworded in commit `aec2334` — the sentence now scopes the floor to longwei's own build ("enforced by an explicit httpcore2>=2.12 constraint in the project's dependency configuration and recorded in the committed lockfiles") and leaves downstream guidance standalone. --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3053) > **docs** [HIGH] ✅ Same paragraph as [3054](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3054) — fixed by the same reword in `aec2334`. The floor does exist in `pyproject.toml` as of `0288996`; the note no longer describes it as something downstream installs inherit.
forgejo-actions left a comment

WuMing

Found 3 issue(s). See inline comments below.

## WuMing Found **3** issue(s). See inline comments below.
Release-Notes.md Outdated
@ -5,11 +5,18 @@ visibility: public
longwei 2.1.2
- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf
- **Security:** httpx2 pinned to 2.12+ with an explicit httpcore2>=2.12 floor, clearing four advisories in the HTTP stack (PYSEC-2026-3844/3846/3848/3849)

docs [LOW]

"pinned to 2.12+" is inaccurate: the dependency is declared as httpx2~=2.12, which is a compatible-release floor (>=2.12, <3.0), not a pin — future 2.x releases are still allowed. The same wording recurs at line 16. Also, the constraint is httpcore2>=2.12.0; writing httpcore2>=2.12 invites confusion about whether 2.12.0 is actually required. Suggest: "httpx2 requirement raised to ~=2.12 with an explicit httpcore2>=2.12.0 floor..."

**docs** [LOW] "pinned to 2.12+" is inaccurate: the dependency is declared as `httpx2~=2.12`, which is a compatible-release floor (>=2.12, <3.0), not a pin — future 2.x releases are still allowed. The same wording recurs at line 16. Also, the constraint is `httpcore2>=2.12.0`; writing `httpcore2>=2.12` invites confusion about whether 2.12.0 is actually required. Suggest: "httpx2 requirement raised to ~=2.12 with an explicit httpcore2>=2.12.0 floor..." <!-- wuming:sha256:82f5ba5a2151628295cb03cc5ad2b4f2a092d833b8eac18f269aab64367898a0 -->
Release-Notes.md Outdated
@ -10,3 +11,4 @@
---
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei's own code has no SOCKS proxy, WebSocket, or multipart file-tuple usage (a search of the library source confirms this), but any application fetching compressed responses through the old httpx2 was exposed to the memory-amplification issue.

docs [LOW]

The exposure assessment enumerates only three of the four advisories: it states longwei has no SOCKS, WebSocket, or multipart file-tuple usage, but says nothing about the request-smuggling advisory (PYSEC-2026-3849) — e.g. whether longwei ever sets Transfer-Encoding or relies on httpx2's auto-generated Content-Length. Complete the sentence (or state that this advisory cannot be triggered by longwei) so readers can tell whether they are affected by all four findings.

**docs** [LOW] The exposure assessment enumerates only three of the four advisories: it states longwei has no SOCKS, WebSocket, or multipart file-tuple usage, but says nothing about the request-smuggling advisory (PYSEC-2026-3849) — e.g. whether longwei ever sets Transfer-Encoding or relies on httpx2's auto-generated Content-Length. Complete the sentence (or state that this advisory cannot be triggered by longwei) so readers can tell whether they are affected by all four findings. <!-- wuming:sha256:4104cd77eadf73e40a168aa8ddc538d4db04f5a7597e89482fc55518344a293a -->
Release-Notes.md Outdated
@ -12,1 +13,4 @@
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei's own code has no SOCKS proxy, WebSocket, or multipart file-tuple usage (a search of the library source confirms this), but any application fetching compressed responses through the old httpx2 was exposed to the memory-amplification issue.
longwei pins httpx2 ~=2.12, and longwei's own build resolves httpcore2 to the patched 2.12.0 — enforced by an explicit httpcore2>=2.12 constraint in the project's dependency configuration and recorded in the committed lockfiles. If you install longwei into your own project, your resolver picks httpx2 and httpcore2 from PyPI independently — make sure your environment resolves httpx2 2.12+ and httpcore2 2.12+. No API changes to longwei, and the full test suite passes unchanged.

docs [MEDIUM]

"recorded in the committed lockfiles" is misleading. The floor lives in pyproject.toml under [tool.uv] constraint-dependencies — that is the file that enforces it — while of the two lockfiles only uv.lock changed; the pylock.toml diff in this PR is empty (as noted in the PR body, the floor changed no resolved versions). Naming an unspecified "project's dependency configuration" also makes the claim impossible for a reader to verify. Suggest: "enforced by an explicit httpcore2>=2.12.0 entry in [tool.uv] constraint-dependencies in pyproject.toml and reflected in uv.lock".

**docs** [MEDIUM] "recorded in the committed lockfiles" is misleading. The floor lives in `pyproject.toml` under `[tool.uv] constraint-dependencies` — that is the file that enforces it — while of the two lockfiles only `uv.lock` changed; the `pylock.toml` diff in this PR is empty (as noted in the PR body, the floor changed no resolved versions). Naming an unspecified "project's dependency configuration" also makes the claim impossible for a reader to verify. Suggest: "enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`". <!-- wuming:sha256:35c6094823db7a629dfe1ee157df12f63b6e0a483ef37a6a34d90dd4c3c25c85 -->
📝 precision fixes to release notes from third review wave
Some checks failed
/ gitleaks (pull_request) Successful in 20s
/ pr-review (pull_request) Successful in 1m38s
/ checks (pull_request) Failing after 11m47s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
3da2737549
- 'pinned' -> requirement raised to ~=2.12 (compatible-release floor);
  constraint written exactly as httpcore2>=2.12.0
- enforcement attributed to [tool.uv] constraint-dependencies in
  pyproject.toml, reflected in uv.lock
- exposure assessment completed for PYSEC-2026-3849 (longwei sets no
  Transfer-Encoding/Content-Length itself; verified by source search)
Author
Collaborator

Wave 3 — all three actioned in commit 3da2737

Release-Notes.md

docs [LOW]

Bullet and line-16 wording corrected: "httpx2 requirement raised to ~=2.12 (>=2.12, <3.0)" and the constraint written exactly as httpcore2>=2.12.0.


Release-Notes.md

docs [MEDIUM]

Adopted your phrasing: "enforced by an explicit httpcore2>=2.12.0 entry in [tool.uv] constraint-dependencies in pyproject.toml and reflected in uv.lock" — the enforcing file is now named, and "lockfiles" plural is gone.


Release-Notes.md

docs [LOW]

Exposure assessment completed: the note now states longwei sets no Transfer-Encoding or Content-Length headers itself, so the request-framing advisory (PYSEC-2026-3849) cannot be triggered through longwei's API. Grounded the same way as the other exposure claims — a search of src/ finds no such header handling.

### Wave 3 — all three actioned in commit `3da2737` [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3059) > **docs** [LOW] ✅ Bullet and line-16 wording corrected: "httpx2 requirement raised to ~=2.12 (>=2.12, <3.0)" and the constraint written exactly as `httpcore2>=2.12.0`. --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3060) > **docs** [MEDIUM] ✅ Adopted your phrasing: "enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`" — the enforcing file is now named, and "lockfiles" plural is gone. --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3061) > **docs** [LOW] ✅ Exposure assessment completed: the note now states longwei sets no `Transfer-Encoding` or `Content-Length` headers itself, so the request-framing advisory (PYSEC-2026-3849) cannot be triggered through longwei's API. Grounded the same way as the other exposure claims — a search of `src/` finds no such header handling.
forgejo-actions left a comment

WuMing

Found 2 issue(s). See inline comments below.

## WuMing Found **2** issue(s). See inline comments below.
Release-Notes.md Outdated
@ -10,3 +11,4 @@
---
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei's own code has no SOCKS proxy, WebSocket, or multipart file-tuple usage (a search of the library source confirms this), nor does it set Transfer-Encoding or Content-Length headers itself, so the request-framing advisory cannot be triggered through longwei's API — but any application fetching compressed responses through the old httpx2 was exposed to the memory-amplification issue.

docs [LOW]

Clarity: this is a single dense run-on paragraph covering four advisories, their impacts, longwei's exposure analysis, and a consumer-impact caveat, and it never names the PYSEC IDs that the summary bullet on line 8 lists. Readers cannot map each described impact to its advisory or tell which findings actually affect them. Suggest reformatting as a short bulleted list, one advisory per bullet with its PYSEC ID and scope (e.g. "affects longwei users" vs. "not reachable via longwei's API"), and splitting the exposure/verification claim into its own sentence.

**docs** [LOW] Clarity: this is a single dense run-on paragraph covering four advisories, their impacts, longwei's exposure analysis, and a consumer-impact caveat, and it never names the PYSEC IDs that the summary bullet on line 8 lists. Readers cannot map each described impact to its advisory or tell which findings actually affect them. Suggest reformatting as a short bulleted list, one advisory per bullet with its PYSEC ID and scope (e.g. "affects longwei users" vs. "not reachable via longwei's API"), and splitting the exposure/verification claim into its own sentence. <!-- wuming:sha256:889ef9a4186ec147149288a089bcb0a7f90419f356a53a1f3bf4e104c3bdab7b -->
Release-Notes.md Outdated
@ -12,1 +13,4 @@
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency. The most serious sends secure WebSocket traffic in plaintext through SOCKS proxies; the others allow memory-amplification denial of service from malicious servers, header injection in multipart uploads, and ambiguous HTTP framing that can enable request smuggling. longwei's own code has no SOCKS proxy, WebSocket, or multipart file-tuple usage (a search of the library source confirms this), nor does it set Transfer-Encoding or Content-Length headers itself, so the request-framing advisory cannot be triggered through longwei's API — but any application fetching compressed responses through the old httpx2 was exposed to the memory-amplification issue.
longwei raises its httpx2 requirement to ~=2.12 (>=2.12, <3.0), and longwei's own build resolves httpcore2 to the patched 2.12.0 — enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`. If you install longwei into your own project, your resolver picks httpx2 and httpcore2 from PyPI independently — make sure your environment resolves httpx2 2.12+ and httpcore2 2.12+. No API changes to longwei, and the full test suite passes unchanged.

docs [MEDIUM]

Accuracy: the note states longwei's build "resolves httpcore2 to the patched 2.12.0", but the mechanism described is a floor (httpcore2>=2.12.0), so a resolver will pick the newest 2.x that satisfies it (e.g. 2.13.x), not necessarily 2.12.0. Stating an exact resolved version in permanent release notes is inaccurate today and will go stale as soon as a newer httpcore2 ships. Reword to reflect the constraint, e.g. "longwei's own build resolves httpcore2 to at least 2.12.0", and keep the exact-version detail in uv.lock where it is verifiable.

**docs** [MEDIUM] Accuracy: the note states longwei's build "resolves httpcore2 to the patched 2.12.0", but the mechanism described is a floor (`httpcore2>=2.12.0`), so a resolver will pick the newest 2.x that satisfies it (e.g. 2.13.x), not necessarily 2.12.0. Stating an exact resolved version in permanent release notes is inaccurate today and will go stale as soon as a newer httpcore2 ships. Reword to reflect the constraint, e.g. "longwei's own build resolves httpcore2 to at least 2.12.0", and keep the exact-version detail in uv.lock where it is verifiable. <!-- wuming:sha256:62ad81b90c6c553a961ebe405af7d83d35ebf511bf3794faafc360bfcdbacd37 -->
📝 per-advisory bullets and floor-accurate wording in release notes
Some checks failed
/ gitleaks (pull_request) Successful in 17s
/ pr-review (pull_request) Successful in 1m20s
/ publish (pull_request) Has been cancelled
/ deploy-docs (pull_request) Has been cancelled
/ checks (pull_request) Has been cancelled
7f8ea93365
Wave-4 review on PR #34: reformat the dense advisory paragraph into one
bullet per PYSEC ID with reachability scope, split the exposure claim into
its own sentence, and state the httpcore2 resolution as 'at least 2.12.0'
(a floor does not pin an exact version).
Author
Collaborator

Wave 4 — both actioned in commit 7f8ea93

Release-Notes.md

docs [MEDIUM]

Reworded exactly as suggested: "longwei's own build resolves httpcore2 to at least 2.12.0" — the exact-version detail now lives only in uv.lock where it is verifiable.


Release-Notes.md

docs [LOW]

Reformatted as one bullet per advisory with its PYSEC ID, severity, and explicit reachability scope ("not reachable through longwei's API" vs "affects longwei users"), with the exposure method (source search) split into its own sentence.

### Wave 4 — both actioned in commit `7f8ea93` [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3065) > **docs** [MEDIUM] ✅ Reworded exactly as suggested: "longwei's own build resolves httpcore2 to at least 2.12.0" — the exact-version detail now lives only in `uv.lock` where it is verifiable. --- [`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3066) > **docs** [LOW] ✅ Reformatted as one bullet per advisory with its PYSEC ID, severity, and explicit reachability scope ("not reachable through longwei's API" vs "affects longwei users"), with the exposure method (source search) split into its own sentence.
forgejo-actions left a comment

WuMing

Found 5 issue(s). See inline comments below.

## WuMing Found **5** issue(s). See inline comments below.
@ -10,3 +11,4 @@
---
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency:

docs [LOW]

This new advisory write-up is inserted between the longwei 2.1.2 changelog entry (which ends at the hashtag line 10) and the standing 'Install / upgrade:' boilerplate at line 27, and it carries no heading of its own. Rendered, it reads as an unlabelled block floating between the release entry and the installation instructions. Consider moving it inside the release entry (before line 10) or giving it an explicit heading (e.g. '### Security detail') so readers can tell which release it documents.

**docs** [LOW] This new advisory write-up is inserted between the longwei 2.1.2 changelog entry (which ends at the hashtag line 10) and the standing 'Install / upgrade:' boilerplate at line 27, and it carries no heading of its own. Rendered, it reads as an unlabelled block floating between the release entry and the installation instructions. Consider moving it inside the release entry (before line 10) or giving it an explicit heading (e.g. '### Security detail') so readers can tell which release it documents. <!-- wuming:sha256:7fa07761abf68cb26d702ee0cd4d816e9f0285c3581391c50bdcea6b6f475c0b -->
marvin8 marked this conversation as resolved
@ -13,0 +15,4 @@
- **PYSEC-2026-3844** (httpcore2, HIGH): secure `wss://` WebSocket traffic sent in plaintext through SOCKS proxies — not reachable through longwei's API (no proxy or WebSocket usage).
- **PYSEC-2026-3846** (httpx2, HIGH): decompression amplification causing memory exhaustion — affects longwei users fetching compressed responses.
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).

docs [MEDIUM]

The non-reachability claim is narrower than the advisory it describes. PYSEC-2026-3848 concerns multipart part headers built from caller-supplied Content-Type/headers, and httpx2's files= parameter also accepts a dict of file-like objects (and raw body content can be multipart too), so ruling out only 'file-tuple usage' does not by itself establish non-reachability. Either widen the evidence (e.g. 'longwei performs no multipart uploads at all, and never passes caller-controlled part headers') or drop the reachability claim, so the note cannot be read as a guarantee that has not been verified.

**docs** [MEDIUM] The non-reachability claim is narrower than the advisory it describes. PYSEC-2026-3848 concerns multipart part headers built from caller-supplied Content-Type/headers, and httpx2's `files=` parameter also accepts a dict of file-like objects (and raw body content can be multipart too), so ruling out only 'file-tuple usage' does not by itself establish non-reachability. Either widen the evidence (e.g. 'longwei performs no multipart uploads at all, and never passes caller-controlled part headers') or drop the reachability claim, so the note cannot be read as a guarantee that has not been verified. <!-- wuming:sha256:c712f82abdba37d35975a27a39730b585ab8cad2342f6b1431848480f75ab0d1 -->
marvin8 marked this conversation as resolved
@ -13,0 +16,4 @@
- **PYSEC-2026-3844** (httpcore2, HIGH): secure `wss://` WebSocket traffic sent in plaintext through SOCKS proxies — not reachable through longwei's API (no proxy or WebSocket usage).
- **PYSEC-2026-3846** (httpx2, HIGH): decompression amplification causing memory exhaustion — affects longwei users fetching compressed responses.
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).
- **PYSEC-2026-3849** (httpx2, MEDIUM): conflicting Content-Length/Transfer-Encoding framing enabling request smuggling — not reachable through longwei's API (it sets neither header itself).

docs [LOW]

The parenthetical is ambiguous: the pronoun 'it' has no clear antecedent in this sentence (longwei? httpx2?). Since the reachability argument is the load-bearing part of the claim, name the subject explicitly, e.g. 'longwei sets neither Content-Length nor Transfer-Encoding itself'.

**docs** [LOW] The parenthetical is ambiguous: the pronoun 'it' has no clear antecedent in this sentence (longwei? httpx2?). Since the reachability argument is the load-bearing part of the claim, name the subject explicitly, e.g. 'longwei sets neither Content-Length nor Transfer-Encoding itself'. <!-- wuming:sha256:2cb6a3d1b052acc74c6a639f681212d55b98e8e257c978e0331195361b5d7850 -->
marvin8 marked this conversation as resolved
@ -13,0 +18,4 @@
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).
- **PYSEC-2026-3849** (httpx2, MEDIUM): conflicting Content-Length/Transfer-Encoding framing enabling request smuggling — not reachable through longwei's API (it sets neither header itself).
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.

docs [LOW]

'The exposure claims reflect a search of the library source' is too vague to be verifiable for a security note — it does not say what was searched or how. Make the method reproducible (e.g. name the symbols/patterns searched: proxy/trust_env, WebSocket, files=/multipart, Transfer-Encoding. Also note this sentence largely restates line 17; consider merging the two to avoid repeating the same reachability statement.

**docs** [LOW] 'The exposure claims reflect a search of the library source' is too vague to be verifiable for a security note — it does not say what was searched or how. Make the method reproducible (e.g. name the symbols/patterns searched: proxy/trust_env, WebSocket, files=/multipart, Transfer-Encoding. Also note this sentence largely restates line 17; consider merging the two to avoid repeating the same reachability statement. <!-- wuming:sha256:7b1576d2d00cf69f4e554ba278fe70eb03a70261d04c789be33525d318e7e4e8 -->
marvin8 marked this conversation as resolved
Release-Notes.md Outdated
@ -13,0 +20,4 @@
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.
longwei raises its httpx2 requirement to ~=2.12 (>=2.12, <3.0), and longwei's own build resolves httpcore2 to at least 2.12.0 — enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`. If you install longwei into your own project, your resolver picks httpx2 and httpcore2 from PyPI independently — make sure your environment resolves httpx2 2.12+ and httpcore2 2.12+. No API changes to longwei, and the full test suite passes unchanged.

docs [MEDIUM]

The consumer guidance here is inaccurate on one point: an installing project does not resolve httpx2 'independently' of longwei, because longwei's own package metadata now declares httpx2~=2.12, which every resolver (pip, uv, poetry) must satisfy. Only httpcore2 is unconstrained downstream, since [tool.uv] constraint-dependencies is a uv-local setting that applies to longwei's own environment and is never exported to consumers. As written, readers may think the declared floor protects their installs, and may waste effort pinning httpx2 while missing that httpcore2 is the real risk. Suggested fix: state that httpx2 2.12+ is guaranteed by longwei's declared requirement for all installers, that the httpcore2>=2.12.0 constraint applies only to longwei's own uv environment, and that projects installing longwei that resolve dependencies with other tools should pin httpcore2>=2.12.0 themselves.

**docs** [MEDIUM] The consumer guidance here is inaccurate on one point: an installing project does not resolve httpx2 'independently' of longwei, because longwei's own package metadata now declares `httpx2~=2.12`, which every resolver (pip, uv, poetry) must satisfy. Only httpcore2 is unconstrained downstream, since `[tool.uv] constraint-dependencies` is a uv-local setting that applies to longwei's own environment and is never exported to consumers. As written, readers may think the declared floor protects their installs, and may waste effort pinning httpx2 while missing that httpcore2 is the real risk. Suggested fix: state that httpx2 2.12+ is guaranteed by longwei's declared requirement for all installers, that the `httpcore2>=2.12.0` constraint applies only to longwei's own uv environment, and that projects installing longwei that resolve dependencies with other tools should pin `httpcore2>=2.12.0` themselves. <!-- wuming:sha256:6b5f3cee0f1180d4c6d7ee88c00f99f19a73fc81bd06a2ec09a92fbb04be05a4 -->
🔧 pin pysentry sources to osv,pypi to stop partial-scan flakes
All checks were successful
/ gitleaks (pull_request) Successful in 24s
/ pr-review (pull_request) Successful in 1m21s
/ checks (pull_request) Successful in 3m43s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
62001297fc
Drops the PyPA advisory-database GitHub download that failed on 3 of the
last 4 checks runs and fail-closed an otherwise clean audit (0 findings).
Sources overlap OSV's PYSEC entries; scan stays deterministic.

Closes #35
forgejo-actions left a comment

WuMing

Found 6 issue(s). See inline comments below.

## WuMing Found **6** issue(s). See inline comments below.
@ -5,11 +5,25 @@ visibility: public
longwei 2.1.2
- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf
- **Security:** httpx2 requirement raised to ~=2.12 with an explicit httpcore2>=2.12.0 floor, clearing four advisories in the HTTP stack (PYSEC-2026-3844/3846/3848/3849)

docs [LOW]

The slash-joined advisory list "PYSEC-2026-3844/3846/3848/3849" is not a valid identifier and is hard to search or copy; list the full IDs (as done in lines 16–19) or link them. Also wrap the constraint in backticks for consistency with the code formatting used elsewhere in these notes: httpcore2>=2.12.0.

**docs** [LOW] The slash-joined advisory list "PYSEC-2026-3844/3846/3848/3849" is not a valid identifier and is hard to search or copy; list the full IDs (as done in lines 16–19) or link them. Also wrap the constraint in backticks for consistency with the code formatting used elsewhere in these notes: `httpcore2>=2.12.0`. <!-- wuming:sha256:ddc2c1fe62eefbd286e33da30a27cd24cc174c3537cc99089d2d1fdcedf7bff1 -->
@ -10,3 +11,4 @@
---
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency:

docs [LOW]

A new prose section is inserted after the entry's hashtag line (line 10) and horizontal rule (line 12) without a heading, so the release entry appears to end before this text begins and the new block reads as orphaned. Add a heading (e.g. ## Security advisories addressed in this release) and move the block above the #Python #PyPI #ActivityPub #OpenSource tag line so the hashtags remain the last line of the entry.

**docs** [LOW] A new prose section is inserted after the entry's hashtag line (line 10) and horizontal rule (line 12) without a heading, so the release entry appears to end before this text begins and the new block reads as orphaned. Add a heading (e.g. `## Security advisories addressed in this release`) and move the block above the `#Python #PyPI #ActivityPub #OpenSource` tag line so the hashtags remain the last line of the entry. <!-- wuming:sha256:609cf4c0b434dd25bc8e651857689b0ab586f2302e5804cb2602c52c36fc1e9f -->
marvin8 marked this conversation as resolved
@ -13,0 +14,4 @@
Four security advisories were published against the HTTP stack longwei depends on — three in httpx2 and one in its httpcore2 dependency:
- **PYSEC-2026-3844** (httpcore2, HIGH): secure `wss://` WebSocket traffic sent in plaintext through SOCKS proxies — not reachable through longwei's API (no proxy or WebSocket usage).
- **PYSEC-2026-3846** (httpx2, HIGH): decompression amplification causing memory exhaustion — affects longwei users fetching compressed responses.

docs [LOW]

This bullet broadens the advisory scope: PYSEC-2026-3846 concerns decompression amplification on streaming responses, but the note says it "affects longwei users fetching compressed responses" without the streaming qualifier. Either scope the statement to streaming responses explicitly, or state plainly that any compressed-response fetch with httpx2 <2.12 was affected, so users can judge whether they are impacted. The tense also shifts between bullets ("affects") and line 21 ("were exposed") — align on past tense for fixed issues.

**docs** [LOW] This bullet broadens the advisory scope: PYSEC-2026-3846 concerns decompression amplification on *streaming* responses, but the note says it "affects longwei users fetching compressed responses" without the streaming qualifier. Either scope the statement to streaming responses explicitly, or state plainly that any compressed-response fetch with httpx2 <2.12 was affected, so users can judge whether they are impacted. The tense also shifts between bullets ("affects") and line 21 ("were exposed") — align on past tense for fixed issues. <!-- wuming:sha256:531ecba9b74fb53c2c5f5f5ea4f03e1ef7c38ffb0c2fe30ac18e38497333c210 -->
marvin8 marked this conversation as resolved
@ -13,0 +16,4 @@
- **PYSEC-2026-3844** (httpcore2, HIGH): secure `wss://` WebSocket traffic sent in plaintext through SOCKS proxies — not reachable through longwei's API (no proxy or WebSocket usage).
- **PYSEC-2026-3846** (httpx2, HIGH): decompression amplification causing memory exhaustion — affects longwei users fetching compressed responses.
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).
- **PYSEC-2026-3849** (httpx2, MEDIUM): conflicting Content-Length/Transfer-Encoding framing enabling request smuggling — not reachable through longwei's API (it sets neither header itself).

docs [LOW]

The pronoun "it" is ambiguous — it reads as though it refers to httpx2, but httpx2 is exactly what auto-generates Content-Length (the root of this advisory). A reader could therefore take the sentence as contradicting itself. Reword to name the subject explicitly, e.g. "…not reachable through longwei's API, since longwei sets neither header itself."

**docs** [LOW] The pronoun "it" is ambiguous — it reads as though it refers to httpx2, but httpx2 is exactly what auto-generates Content-Length (the root of this advisory). A reader could therefore take the sentence as contradicting itself. Reword to name the subject explicitly, e.g. "…not reachable through longwei's API, since longwei sets neither header itself." <!-- wuming:sha256:de2521229640e8656d81f5439bd526cf01a808be14ec77a350f89d9efe6cdce9 -->
marvin8 marked this conversation as resolved
@ -13,0 +18,4 @@
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).
- **PYSEC-2026-3849** (httpx2, MEDIUM): conflicting Content-Length/Transfer-Encoding framing enabling request smuggling — not reachable through longwei's API (it sets neither header itself).
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.

docs [MEDIUM]

This is process/meta commentary about how the exposure assessment was performed ("a search of the library source"), which belongs in the PR description or a security advisory, not in user-facing release notes. "The exposure claims" is also self-referential and vague about what is being claimed. Recommend deleting the first sentence and keeping only the user-relevant impact statement (e.g. "Applications that fetched compressed responses with httpx2 <2.12 were exposed to PYSEC-2026-3846."), and noting the scope (streaming responses) consistently with line 17.

**docs** [MEDIUM] This is process/meta commentary about how the exposure assessment was performed ("a search of the library source"), which belongs in the PR description or a security advisory, not in user-facing release notes. "The exposure claims" is also self-referential and vague about what is being claimed. Recommend deleting the first sentence and keeping only the user-relevant impact statement (e.g. "Applications that fetched compressed responses with httpx2 <2.12 were exposed to PYSEC-2026-3846."), and noting the scope (streaming responses) consistently with line 17. <!-- wuming:sha256:57f7d3efe7c4ea95f306030ba70825a553a28f941e2523186af7f33c7946cdee -->
marvin8 marked this conversation as resolved
Release-Notes.md Outdated
@ -13,0 +20,4 @@
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.
longwei raises its httpx2 requirement to ~=2.12 (>=2.12, <3.0), and longwei's own build resolves httpcore2 to at least 2.12.0 — enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`. If you install longwei into your own project, your resolver picks httpx2 and httpcore2 from PyPI independently — make sure your environment resolves httpx2 2.12+ and httpcore2 2.12+. No API changes to longwei, and the full test suite passes unchanged.

docs [MEDIUM]

The downstream guidance is misleading for httpx2. longwei declares httpx2 as a direct dependency with ~=2.12, so any environment that installs this version of longwei is already forced to resolve httpx2 >=2.12,<3.0 — users cannot get an unpatched httpx2 from a correct install, and the two packages are not chosen "independently" in the same sense. Only httpcore2 lacks a floor in httpx2 2.12's metadata, so only httpcore2 needs a user-side or downstream constraint. Also, uv.lock is a lockfile that only matters for longwei's own development/CI, not for consumers, so mentioning it here can confuse readers. Suggest rewording to something like: "longwei's own environment is pinned via an explicit httpcore2>=2.12.0 constraint in [tool.uv] constraint-dependencies; because httpx2 2.12 does not declare a httpcore2 floor, consumers whose projects resolve httpcore2 independently should ensure their own environment resolves httpcore2 2.12+." Consider also splitting this long single block into two short paragraphs.

**docs** [MEDIUM] The downstream guidance is misleading for httpx2. longwei declares httpx2 as a direct dependency with `~=2.12`, so any environment that installs this version of longwei is already forced to resolve httpx2 >=2.12,<3.0 — users cannot get an unpatched httpx2 from a correct install, and the two packages are not chosen "independently" in the same sense. Only httpcore2 lacks a floor in httpx2 2.12's metadata, so only httpcore2 needs a user-side or downstream constraint. Also, `uv.lock` is a lockfile that only matters for longwei's own development/CI, not for consumers, so mentioning it here can confuse readers. Suggest rewording to something like: "longwei's own environment is pinned via an explicit `httpcore2>=2.12.0` constraint in `[tool.uv] constraint-dependencies`; because httpx2 2.12 does not declare a httpcore2 floor, consumers whose projects resolve httpcore2 independently should ensure their own environment resolves httpcore2 2.12+." Consider also splitting this long single block into two short paragraphs. <!-- wuming:sha256:b3abc013bcd49eba7338ff2c77945800436ed953525b3e379d4b020e40f10ff5 -->
📝 drop the already-released mkdocs-material advisory from the intro post
All checks were successful
/ gitleaks (pull_request) Successful in 20s
/ pr-review (pull_request) Successful in 1m21s
/ checks (pull_request) Successful in 3m11s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
b1fe70eacc
forgejo-actions left a comment

WuMing

Found 1 issue(s). See inline comments below.

## WuMing Found **1** issue(s). See inline comments below.
@ -5,3 +5,3 @@
longwei 2.1.2
- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf
- **Security:** httpx2 requirement raised to ~=2.12 with an explicit httpcore2>=2.12.0 floor, clearing four advisories in the HTTP stack (PYSEC-2026-3844/3846/3848/3849)

docs [MEDIUM]

This line replaces the pre-existing security bullet for the mkdocs-material pin (GHSA-xvg9-69gf-fjrf) rather than being added alongside it, so the 2.1.2 entry now silently drops a previously documented security fix — readers of the release notes no longer learn that mkdocs-material is pinned to >=9.7.7. Restore the mkdocs-material bullet as its own list item and add the httpx2/httpcore2 bullet as a second item, so both security changes remain documented.

**docs** [MEDIUM] This line replaces the pre-existing security bullet for the mkdocs-material pin (GHSA-xvg9-69gf-fjrf) rather than being added alongside it, so the 2.1.2 entry now silently drops a previously documented security fix — readers of the release notes no longer learn that mkdocs-material is pinned to >=9.7.7. Restore the mkdocs-material bullet as its own list item and add the httpx2/httpcore2 bullet as a second item, so both security changes remain documented. <!-- wuming:sha256:a63379fa913db14078e6442ab9117db3ff9b31162dfc006f3e664d6bdc3e95ae -->
Author
Collaborator

Release-Notes.md

docs [MEDIUM]

🔴 Declined — deliberate maintainer decision. The mkdocs-material pin (GHSA-xvg9-69gf-fjrf) shipped in the already-released 2.1.2 (commit b8b2d0f on main, before the 2.1.1 → 2.1.2 version bump), so its bullet is stale content for this pending announcement rather than a dropped fix. The removal in b1fe70e is intentional; the constraint itself remains in [tool.uv] constraint-dependencies.

[`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3089) > **docs** [MEDIUM] 🔴 Declined — deliberate maintainer decision. The mkdocs-material pin (GHSA-xvg9-69gf-fjrf) shipped in the already-released 2.1.2 (commit `b8b2d0f` on `main`, before the 2.1.1 → 2.1.2 version bump), so its bullet is stale content for this pending announcement rather than a dropped fix. The removal in `b1fe70e` is intentional; the constraint itself remains in `[tool.uv] constraint-dependencies`.
Author
Collaborator

Waves 284/285 — maintainer triage: 2 dismissed with evidence, 9 noted but not actioned this release

Dismissed — downstream httpcore2 exposure is structurally impossible

#3073 · #3081

docs [MEDIUM]

🔴 The premise no longer holds: the maintainer reviewed the httpx2 2.12 source and confirmed it requires httpcore2 of the same version. Verified independently from the published httpx2 2.12.0 wheel metadata:

Requires-Dist: httpcore2==2.12.0; sys_platform != 'emscripten'

That is an exact pin — a correct install of httpx2 2.12.0 cannot pair with any other httpcore2, so there is no downstream httpcore2 exposure for the guidance to address, and no resolver freedom for users to check. The release-notes text stays as the maintainer wrote it; the committed httpcore2>=2.12.0 constraint remains purely as defence-in-depth.

Not actioned this release — maintainer has reviewed the list and is shipping the notes as-is

  • Part-header scope of PYSEC-2026-3848 (#3074): noted; the files= dict-of-file-objects path is a fair observation for a future pass.
  • Exposure-method commentary placement (#3082) and specificity (#3076): noted.
  • PYSEC-2026-3846 streaming qualifier (#3084): noted.
  • Ambiguous "it" antecedent (#3075, #3083): noted.
  • Section heading after the hashtags (#3077, #3085): noted.
  • Slash-joined PYSEC IDs / backticks (#3086): noted.

None of these block the release; the maintainer has seen the full list and chosen to keep this announcement's wording for 2.1.x, folding the rest into a future docs pass.

### Waves 284/285 — maintainer triage: 2 dismissed with evidence, 9 noted but not actioned this release **Dismissed — downstream httpcore2 exposure is structurally impossible** [#3073](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3073) · [#3081](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3081) > **docs** [MEDIUM] 🔴 The premise no longer holds: the maintainer reviewed the httpx2 2.12 source and confirmed it requires httpcore2 of the same version. Verified independently from the published httpx2 2.12.0 wheel metadata: ``` Requires-Dist: httpcore2==2.12.0; sys_platform != 'emscripten' ``` That is an exact pin — a correct install of httpx2 2.12.0 cannot pair with any other httpcore2, so there is no downstream httpcore2 exposure for the guidance to address, and no resolver freedom for users to check. The release-notes text stays as the maintainer wrote it; the committed `httpcore2>=2.12.0` constraint remains purely as defence-in-depth. **Not actioned this release — maintainer has reviewed the list and is shipping the notes as-is** - Part-header scope of PYSEC-2026-3848 ([#3074](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3074)): noted; the `files=` dict-of-file-objects path is a fair observation for a future pass. - Exposure-method commentary placement ([#3082](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3082)) and specificity ([#3076](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3076)): noted. - PYSEC-2026-3846 streaming qualifier ([#3084](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3084)): noted. - Ambiguous "it" antecedent ([#3075](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3075), [#3083](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3083)): noted. - Section heading after the hashtags ([#3077](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3077), [#3085](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3085)): noted. - Slash-joined PYSEC IDs / backticks ([#3086](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3086)): noted. None of these block the release; the maintainer has seen the full list and chosen to keep this announcement's wording for 2.1.x, folding the rest into a future docs pass.
📝 correct the consumer guidance in the release notes
All checks were successful
/ gitleaks (pull_request) Successful in 17s
/ pr-review (pull_request) Successful in 1m17s
/ checks (pull_request) Successful in 3m36s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
1518eb6bf9
httpx2 is declared by longwei (~=2.12) and httpx2 2.12 pins its matching
httpcore2 exactly (==2.12.0 in wheel metadata), so installers resolve
both automatically — the 'pick independently / check your environment'
wording overstated resolver freedom.
forgejo-actions left a comment

WuMing

Found 4 issue(s). See inline comments below.

## WuMing Found **4** issue(s). See inline comments below.
@ -5,3 +5,3 @@
longwei 2.1.2
- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf
- **Security:** httpx2 requirement raised to ~=2.12 with an explicit httpcore2>=2.12.0 floor, clearing four advisories in the HTTP stack (PYSEC-2026-3844/3846/3848/3849)

docs [MEDIUM]

The summary bullet calls the httpcore2 floor part of the "requirement", but the floor lives only in longwei's dev-only [tool.uv] constraint-dependencies and is not part of the published httpx2~=2.12 requirement. Reword to distinguish the published requirement (httpx2~=2.12) from the build-time/dev constraint that forces httpcore2>=2.12.0, so readers do not assume the floor is enforced during their own install.

**docs** [MEDIUM] The summary bullet calls the httpcore2 floor part of the "requirement", but the floor lives only in longwei's dev-only `[tool.uv] constraint-dependencies` and is not part of the published `httpx2~=2.12` requirement. Reword to distinguish the published requirement (`httpx2~=2.12`) from the build-time/dev constraint that forces httpcore2>=2.12.0, so readers do not assume the floor is enforced during their own install. <!-- wuming:sha256:b43658e4dbcb87e471820401f339d74ac3530d9fdaf70662b08cb0a3436f126e -->
@ -13,0 +17,4 @@
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).
- **PYSEC-2026-3849** (httpx2, MEDIUM): conflicting Content-Length/Transfer-Encoding framing enabling request smuggling — not reachable through longwei's API (it sets neither header itself).
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.

docs [LOW]

"The exposure claims reflect a search of the library source" is too vague to support the four reachability verdicts above it: it names no revision/tag, no tooling, and no date. Add the specific revision searched and how it was searched (e.g. "grep of longwei @ <commit/ref> for proxy=, files=, Transfer-Encoding"), or drop the sentence, so the "not reachable" claims are verifiable.

**docs** [LOW] "The exposure claims reflect a search of the library source" is too vague to support the four reachability verdicts above it: it names no revision/tag, no tooling, and no date. Add the specific revision searched and how it was searched (e.g. "grep of longwei @ <commit/ref> for `proxy=`, `files=`, `Transfer-Encoding`"), or drop the sentence, so the "not reachable" claims are verifiable. <!-- wuming:sha256:7c934554c19a6ac2e8f1d1a40c0d31ebf75653873839e30a38d8b7b9acf4f550 -->
marvin8 marked this conversation as resolved
@ -13,0 +19,4 @@
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.
longwei raises its httpx2 requirement to ~=2.12 (>=2.12, <3.0), and longwei's own build resolves httpcore2 to at least 2.12.0 — enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`. Installing longwei into your own project resolves both for you: resolvers must satisfy longwei's declared `httpx2~=2.12` requirement, and httpx2 pins its matching httpcore2 exactly (`httpcore2==2.12.0`), so no manual version checks are needed. No API changes to longwei, and the full test suite passes unchanged.

docs [CRITICAL]

Factually wrong and contradicts this PR's own rationale. The PR notes that httpx2 2.12.0 declares httpcore2 with no version floor, so the patched httpcore2 is only guaranteed by the declared constraint. Stating that "httpx2 pins its matching httpcore2 exactly (httpcore2==2.12.0)" tells users the transitive dependency is safe regardless of the floor, which is not true. Rewrite to say httpx2 does not narrow httpcore2 and that the floor is what guarantees >=2.12.0 (and only for builds that apply longwei's constraints).

**docs** [CRITICAL] Factually wrong and contradicts this PR's own rationale. The PR notes that httpx2 2.12.0 declares httpcore2 with *no* version floor, so the patched httpcore2 is only guaranteed by the declared constraint. Stating that "httpx2 pins its matching httpcore2 exactly (`httpcore2==2.12.0`)" tells users the transitive dependency is safe regardless of the floor, which is not true. Rewrite to say httpx2 does not narrow httpcore2 and that the floor is what guarantees >=2.12.0 (and only for builds that apply longwei's constraints). <!-- wuming:sha256:5c72123539c50040da00073f784afc0771743d1bf4eb29ab5605405e9a90a590 -->

docs [HIGH]

[tool.uv] constraint-dependencies is a uv-only setting in the project's own pyproject.toml; it is not part of the published package metadata and is ignored by pip/Poetry/other resolvers. So the httpcore2 floor does not propagate to users installing longwei, and—since httpx2's metadata has no floor—a downstream resolve can still pick an unpatched httpcore2. The sentences "Installing longwei into your own project resolves both for you ... so no manual version checks are needed" therefore overstate the protection. Either add the floor to the published dependency metadata (e.g. a real httpcore2>=2.12.0 requirement) or reword to state clearly that consumers using non-uv resolvers may need to pin httpcore2 themselves.

**docs** [HIGH] `[tool.uv] constraint-dependencies` is a uv-only setting in the project's own pyproject.toml; it is not part of the published package metadata and is ignored by pip/Poetry/other resolvers. So the httpcore2 floor does not propagate to users installing longwei, and—since httpx2's metadata has no floor—a downstream resolve can still pick an unpatched httpcore2. The sentences "Installing longwei into your own project resolves both for you ... so no manual version checks are needed" therefore overstate the protection. Either add the floor to the published dependency metadata (e.g. a real `httpcore2>=2.12.0` requirement) or reword to state clearly that consumers using non-uv resolvers may need to pin httpcore2 themselves. <!-- wuming:sha256:5c72123539c50040da00073f784afc0771743d1bf4eb29ab5605405e9a90a590 -->
marvin8 marked this conversation as resolved
Author
Collaborator

Wave 287 — CRITICAL/HIGH dismissed with artifact evidence; source of the confusion (our PR body) corrected

The premise shared by both high-severity findings — "httpx2 2.12.0 declares httpcore2 with no version floor" — is false. It was inherited from this PR's own description, which has now been corrected. The published httpx2 2.12.0 wheel metadata states:

Requires-Dist: httpcore2==2.12.0; sys_platform != 'emscripten'

That is an exact pin, enforced by every resolver (pip, uv, poetry) from the wheel's METADATA — not a uv.lock rendering artifact. A correct install of httpx2 2.12.0 cannot pair with any other httpcore2. (The uv.lock entry shows no specifier because uv bakes exact pins into the resolved entry; the wheel is the authoritative artifact for what downstream resolvers enforce.)

Release-Notes.md #3094

docs [CRITICAL]

🔴 Declined — the sentence "httpx2 pins its matching httpcore2 exactly (httpcore2==2.12.0)" is factually correct per the wheel metadata above. The "contradiction" was with the PR body's stale note, which is the text that was wrong; it has been rewritten to state the exact pin and reframe the [tool.uv] floor as defence-in-depth for longwei's own builds.


Release-Notes.md #3095

docs [HIGH]

🔴 Declined — the finding's true premise (constraint-dependencies is uv-only and does not propagate) is acknowledged and now stated explicitly in the PR body. But its conclusion does not follow: downstream protection does not come from the floor, it comes from httpx2's own ==2.12.0 pin, which pip/Poetry enforce. "No manual version checks are needed" is therefore accurate — non-uv resolvers cannot pick an unpatched httpcore2 alongside httpx2 2.12.0.


Release-Notes.md #3096

docs [MEDIUM]

🟡 Noted for the maintainer — the bullet's "with an explicit httpcore2>=2.12.0 floor" phrasing sits next to the published-requirement wording, and distinguishing build-time constraint from published requirement is a fair point. Left as-is pending the maintainer's call (the notes have been through their review).


Release-Notes.md #3097

docs [LOW]

🔴 Repeat of the search-method cluster already dispositioned in the waves-284/285 triage (consolidated reply) — same substance, recomputed hash. Stays noted, not actioned this release.

### Wave 287 — CRITICAL/HIGH dismissed with artifact evidence; source of the confusion (our PR body) corrected The premise shared by both high-severity findings — "httpx2 2.12.0 declares httpcore2 with *no* version floor" — is false. It was inherited from this PR's own description, which has now been corrected. The published httpx2 2.12.0 wheel metadata states: ``` Requires-Dist: httpcore2==2.12.0; sys_platform != 'emscripten' ``` That is an exact pin, enforced by every resolver (pip, uv, poetry) from the wheel's METADATA — not a uv.lock rendering artifact. A correct install of httpx2 2.12.0 cannot pair with any other httpcore2. (The uv.lock entry shows no specifier because uv bakes exact pins into the resolved entry; the wheel is the authoritative artifact for what downstream resolvers enforce.) [`Release-Notes.md` #3094](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3094) > **docs** [CRITICAL] 🔴 Declined — the sentence "httpx2 pins its matching httpcore2 exactly (`httpcore2==2.12.0`)" is factually correct per the wheel metadata above. The "contradiction" was with the PR body's stale note, which is the text that was wrong; it has been rewritten to state the exact pin and reframe the `[tool.uv]` floor as defence-in-depth for longwei's own builds. --- [`Release-Notes.md` #3095](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3095) > **docs** [HIGH] 🔴 Declined — the finding's true premise (constraint-dependencies is uv-only and does not propagate) is acknowledged and now stated explicitly in the PR body. But its conclusion does not follow: downstream protection does not come from the floor, it comes from httpx2's own `==2.12.0` pin, which pip/Poetry enforce. "No manual version checks are needed" is therefore accurate — non-uv resolvers cannot pick an unpatched httpcore2 alongside httpx2 2.12.0. --- [`Release-Notes.md` #3096](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3096) > **docs** [MEDIUM] 🟡 Noted for the maintainer — the bullet's "with an explicit httpcore2>=2.12.0 floor" phrasing sits next to the published-requirement wording, and distinguishing build-time constraint from published requirement is a fair point. Left as-is pending the maintainer's call (the notes have been through their review). --- [`Release-Notes.md` #3097](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3097) > **docs** [LOW] 🔴 Repeat of the search-method cluster already dispositioned in the waves-284/285 triage ([consolidated reply](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3092)) — same substance, recomputed hash. Stays noted, not actioned this release.
📝 drop the build-side floor from the intro security bullet
All checks were successful
/ gitleaks (pull_request) Successful in 18s
/ pr-review (pull_request) Successful in 1m54s
/ checks (pull_request) Successful in 3m45s
/ publish (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
8b764f8fb8
The bullet sat next to the published-requirement wording, inviting the
read that pip enforces the httpcore2 floor. The constraint is build-side
defence-in-depth; httpx2 itself pins its matching httpcore2 exactly.
Author
Collaborator

Release-Notes.md

docs [MEDIUM]

Actioned in commit 8b764f8 — the bullet now reads "httpx2 requirement raised to ~=2.12 (which pins its matching httpcore2)", attributing the httpcore2 clearance to the upstream pin rather than the build-side constraint. The published requirement and the [tool.uv] defence-in-depth floor are no longer conflated in the bullet.

[`Release-Notes.md`](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3096issuecomment-3096) > **docs** [MEDIUM] ✅ Actioned in commit `8b764f8` — the bullet now reads "httpx2 requirement raised to ~=2.12 (which pins its matching httpcore2)", attributing the httpcore2 clearance to the upstream pin rather than the build-side constraint. The published requirement and the `[tool.uv]` defence-in-depth floor are no longer conflated in the bullet.
forgejo-actions left a comment

WuMing

Found 3 issue(s). See inline comments below.

## WuMing Found **3** issue(s). See inline comments below.
@ -5,3 +5,3 @@
longwei 2.1.2
- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf
- **Security:** httpx2 requirement raised to ~=2.12 (which pins its matching httpcore2), clearing four advisories in the HTTP stack (PYSEC-2026-3844/3846/3848/3849)

docs [MEDIUM]

This bullet replaces the existing changelog entry rather than adding to it: the line "- Security: mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf" is deleted in this diff. If that mkdocs-material fix is still part of the 2.1.2 release, the changelog now loses a security item that users were previously told about. Fix: keep the mkdocs-material bullet and add the httpx2 bullet as a separate line (or confirm and state explicitly in the PR that the mkdocs-material note is being withdrawn).

**docs** [MEDIUM] This bullet replaces the existing changelog entry rather than adding to it: the line "- **Security:** mkdocs-material now pinned to version 9.7.7 or higher to address GHSA-xvg9-69gf-fjrf" is deleted in this diff. If that mkdocs-material fix is still part of the 2.1.2 release, the changelog now loses a security item that users were previously told about. Fix: keep the mkdocs-material bullet and add the httpx2 bullet as a separate line (or confirm and state explicitly in the PR that the mkdocs-material note is being withdrawn). <!-- wuming:sha256:495d4455812393f11479d7c057624803799208e82923501c7bbe2dad36974aee -->
marvin8 marked this conversation as resolved
@ -13,0 +17,4 @@
- **PYSEC-2026-3848** (httpx2, MEDIUM): multipart part-header injection via the `files=` tuple API — not reachable through longwei's API (no multipart file-tuple usage).
- **PYSEC-2026-3849** (httpx2, MEDIUM): conflicting Content-Length/Transfer-Encoding framing enabling request smuggling — not reachable through longwei's API (it sets neither header itself).
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.

docs [LOW]

"The exposure claims reflect a search of the library source" is too vague to be verifiable by a reader and does not say what was searched or how. Fix: name the check concretely, e.g. "based on a grep of longwei's source for proxy configuration, WebSocket use, multipart files= tuples, and explicit Content-Length/Transfer-Encoding headers", so the non-reachability claims on lines 15-18 can be independently validated.

**docs** [LOW] "The exposure claims reflect a search of the library source" is too vague to be verifiable by a reader and does not say what was searched or how. Fix: name the check concretely, e.g. "based on a grep of longwei's source for proxy configuration, WebSocket use, multipart `files=` tuples, and explicit Content-Length/Transfer-Encoding headers", so the non-reachability claims on lines 15-18 can be independently validated. <!-- wuming:sha256:e4c7d04d3a8b5c24c956cae39b7a8af234b775883c4ab9d352292ec9902e471c -->
marvin8 marked this conversation as resolved
@ -13,0 +19,4 @@
The exposure claims reflect a search of the library source. Applications fetching compressed responses through the old httpx2 were exposed to PYSEC-2026-3846.
longwei raises its httpx2 requirement to ~=2.12 (>=2.12, <3.0), and longwei's own build resolves httpcore2 to at least 2.12.0 — enforced by an explicit `httpcore2>=2.12.0` entry in `[tool.uv] constraint-dependencies` in `pyproject.toml` and reflected in `uv.lock`. Installing longwei into your own project resolves both for you: resolvers must satisfy longwei's declared `httpx2~=2.12` requirement, and httpx2 pins its matching httpcore2 exactly (`httpcore2==2.12.0`), so no manual version checks are needed. No API changes to longwei, and the full test suite passes unchanged.

docs [HIGH]

This sentence says the httpcore2>=2.12.0 constraint is "reflected in uv.lock", but the PR description states the project's lockfile is pylock.toml ("pylock.toml regenerated ... its diff is empty from 0288996"). Naming a lockfile that the project does not use will send users looking in the wrong place, and since the resolution was unchanged by the floor, "reflected in" the lock is also misleading. Fix: refer to pylock.toml, and reword to say the lock already pins httpcore2 at 2.12.0 (the constraint is declarative defence-in-depth, not something that changed the pinned version).

**docs** [HIGH] This sentence says the `httpcore2>=2.12.0` constraint is "reflected in `uv.lock`", but the PR description states the project's lockfile is `pylock.toml` ("`pylock.toml` regenerated ... its diff is empty from `0288996`"). Naming a lockfile that the project does not use will send users looking in the wrong place, and since the resolution was unchanged by the floor, "reflected in" the lock is also misleading. Fix: refer to `pylock.toml`, and reword to say the lock already pins httpcore2 at 2.12.0 (the constraint is declarative defence-in-depth, not something that changed the pinned version). <!-- wuming:sha256:d3928e3bcd581ee42c46f6d1136daec8bbae8910702a94b8db31057c242a6fde -->
marvin8 marked this conversation as resolved
Author
Collaborator

Wave 288 — one declined with evidence, two duplicates of dispositioned findings

Release-Notes.md #3103

docs [HIGH]

🔴 Declined — the premise conflates the repo's two lockfiles. This project has both: uv.lock (uv's) and pylock.toml (the PEP 751 export). The PR body's note says only that pylock.toml's diff was empty from 0288996 (the floor changes no resolved versions and the pylock format carries no constraint metadata); it does not say pylock.toml is the project's lockfile. "Reflected in uv.lock" is verifiably true — the constraints block gained this line in 0288996, as quoted in the wave-2 reply:

 constraints = [
     { name = "click", specifier = ">=8.3.3" },
     { name = "h2", specifier = ">=4.4.1" },
+    { name = "httpcore2", specifier = ">=2.12.0" },

Release-Notes.md #3104

docs [MEDIUM]

🔴 Duplicate of the wave-286 finding (declined here): the mkdocs-material pin shipped in the already-released 2.1.2 (b8b2d0f predates the 2.1.2 version bump), so its bullet is stale content for this pending announcement and its removal was a deliberate maintainer decision.


Release-Notes.md #3105

docs [LOW]

🔴 Duplicate of the search-method cluster, third re-raise — dispositioned as noted-not-actioned in the waves-284/285 triage. Unchanged: the maintainer has the list and is shipping this announcement's wording as-is.

### Wave 288 — one declined with evidence, two duplicates of dispositioned findings [`Release-Notes.md` #3103](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3103) > **docs** [HIGH] 🔴 Declined — the premise conflates the repo's two lockfiles. This project has both: `uv.lock` (uv's) and `pylock.toml` (the PEP 751 export). The PR body's note says only that `pylock.toml`'s diff was empty from `0288996` (the floor changes no resolved versions and the pylock format carries no constraint metadata); it does not say `pylock.toml` is the project's lockfile. "Reflected in `uv.lock`" is verifiably true — the constraints block gained this line in `0288996`, as quoted in the [wave-2 reply](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3058): ```diff constraints = [ { name = "click", specifier = ">=8.3.3" }, { name = "h2", specifier = ">=4.4.1" }, + { name = "httpcore2", specifier = ">=2.12.0" }, ``` --- [`Release-Notes.md` #3104](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3104) > **docs** [MEDIUM] 🔴 Duplicate of the wave-286 finding ([declined here](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3091)): the mkdocs-material pin shipped in the already-released 2.1.2 (`b8b2d0f` predates the 2.1.2 version bump), so its bullet is stale content for this pending announcement and its removal was a deliberate maintainer decision. --- [`Release-Notes.md` #3105](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3105) > **docs** [LOW] 🔴 Duplicate of the search-method cluster, third re-raise — dispositioned as noted-not-actioned in the [waves-284/285 triage](https://forge.marvin8.zone/marvin8/longwei/pulls/34#issuecomment-3092). Unchanged: the maintainer has the list and is shipping this announcement's wording as-is.
marvin8 approved these changes 2026-09-13 19:50:18 +00:00
marvin8 manually merged commit 5769c50394 into main 2026-09-13 19:51:24 +00:00
Sign in to join this conversation.
No description provided.