Update hackney to 4.x to address advisories - #4907
Merged
Merged
Conversation
rorymckinley
force-pushed
the
4905-hackney-updates
branch
from
July 8, 2026 10:37
4600303 to
8ebaa18
Compare
rorymckinley
force-pushed
the
4905-hackney-updates
branch
from
July 9, 2026 05:17
8ebaa18 to
941399b
Compare
hackney 4.x carries the fixes for the four advisories .mix_audit.ignore was suppressing, so both ignore lists shrink to what is genuinely unfixable. - hackney 4.4.5 -> 4.6.0, which fixes a hackney_conn process leak on connections flagged no_reuse. 4.6.0 is the ceiling: 4.6.1 and later require h2 ~> 0.11.0 while hackney's own webtransport dep requires h2 ~> 0.10.4. - swoosh -> 1.26.3, fixing CVE-2026-54893. This needs tidewave 0.8, because swoosh 1.18.3 and later require req ~> 0.5.10, and every req that new requires mime ~> 2.0, which google_gax pins away from. tidewave 0.8 drops req altogether, so req leaves the tree and takes CVE-2026-49755 with it. - tzdata tracks upstream master for `hackney ~> 1.17 or ~> 4.0` (lau/tzdata#170), which is not on Hex yet. - Drop metrics and unicode_util_compat from the lock; hackney 4 depends on neither. .mix_audit.ignore is now empty and hex_audit/0 is down to the two cowlib advisories with no patched release. The file stays because CI passes it via --ignore-file and mix_audit reads it with File.read!/1. Filter the httpoison 3 callback contract warnings: hackney 4 made a client handle a pid where it was a reference, but HTTPoison.AsyncResponse.t() still declares id: reference().
hackney 4 negotiates HTTP/2 by default where 1.x was HTTP/1.1 only. Concurrent requests to one host multiplex onto a single connection, so retiring that connection fails every in-flight request at once. mix lightning.install_schemas lost about a quarter of its fetches to :closed this way. They were retried, but a transport change is not something this upgrade needs. tzdata's autoupdater works again now that it accepts hackney 4, so drop the config that disabled it. Disable it in test instead: it polls IANA a few seconds after boot, and CI starts from a fresh container every run.
hackney keeps a closing pooled connection alive briefly so requests that raced
the checkout get an answer instead of crashing the caller. It means to answer
{:closed, _} -- the comment in hackney_conn.erl says as much -- but the
catch-all it falls through to answers :invalid_state, which was not in
@retriable_reasons. A package hitting that race was skipped after one attempt.
edgurgel/httpoison#511 already retypes the async struct ids as `id: pid` and drops the dead `stream_next/1` clause, so these three filters are temporary. It merged on 2026-07-05 and 3.0.0 shipped on 2026-06-14, so there is nothing to do but wait for the next release. Record that so the filters get removed then rather than outliving the bug.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4907 +/- ##
=====================================
Coverage 90.4% 90.5%
=====================================
Files 425 425
Lines 20237 20237
=====================================
+ Hits 18304 18306 +2
+ Misses 1933 1931 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
midigofrank
marked this pull request as ready for review
July 29, 2026 03:30
|
This PR is purely a dependency upgrade: hackney 4.6, httpoison 3.0, sentry 13.2, swoosh 1.26, tidewave 0.8, tzdata from master, along with associated dialyzer/mix_audit ignore updates and small changes to Security Review ✅
|
midigofrank
approved these changes
Jul 29, 2026
cowboy 2.18.0 and cowlib 2.19.0 clear EEF-CVE-2026-65624 and EEF-CVE-2026-59248. Both were published on 2026-07-28, about an hour after this branch's last lint run, so hex.audit was green then and would fail now. Back to exit 0 with only the two cowlib records that carry no fixed event. finch backs the app's own Lightning.Finch pool and the default Tesla adapter, but its version was resolving entirely through prom_ex and goth. Dropping or loosening either would break the supervision tree with no compile-time signal. Sentry 13 defaulting its client to Finch makes it worth stating outright. tzdata takes an explicit ref. The lock pinned the commit, but `github:` with no ref tracks the default branch, so unlocking it would pull whatever master happens to be at that moment into a release. Also drop the guess that the fix lands in 1.1.5: master still declares 1.1.4 and no release is scheduled.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Updates
hackneyfrom 1.25 to 4.6 to pick up the fixes for the four advisories we were suppressing in.mix_audit.ignore. Everything else here follows from that upgrade.Closes #4905
Dependency changes
hackney1.25 → 4.6.0,httpoison2.2.3 → 3.0.0 (3.0 is the release that requires hackney 4),sentry10.9 → 13.2 (its default HTTP client moved from Hackney to Finch along the way).swoosh1.18.2 → 1.26.3, fixing CVE-2026-54893. This forcedtidewave(dev-only) 0.5.6 → 0.8.0: swoosh 1.18.3+ requiresreq ~> 0.5.10, and everyreqthat new requiresmime ~> 2.0, whichgoogle_gaxpins away from. tidewave 0.8 droppedreqentirely, and since tidewave was the only thing pulling it in,reqleaves the tree and takes CVE-2026-49755 with it.tzdatanow tracks upstreammasterfor lau/tzdata#170 (hackney ~> 1.17 or ~> 4.0), pinned to commit766f38de. That is not on Hex yet — 1.1.4 predates it — and it is what lets tzdata keep its autoupdater running on hackney 4.metrics,unicode_util_compat(hackney 4 depends on neither) andreq. Added:h2,quic,webtransport(hackney 4's own deps).Result:
.mix_audit.ignoreis now empty, and thehex_audit/0list inmix.exsis down to the twocowlibadvisories that have no patched release.Validation steps
mix deps.audit --ignore-file .mix_audit.ignore→ "No vulnerabilities found", with nothing in the ignore file.mix hex.audit→ only the twocowlibentries listed as ignored, and no "entry ... can be removed" warnings.mix lightning.install_schemas→ completes with107 installed, 0 skippedand no transient-error warnings.mix verify→ format, dialyzer, credo and sobelow all pass.MAIL_PROVIDER=mailgun, send a test email. Swoosh still usesSwoosh.ApiClient.Hackney, so this is swoosh 1.26 on hackney 4.Additional notes for the reviewer
override: trueare load-bearing.hackneyis overridden becausephoenix_swoosh1.2.1 (latest) still declareshackney ~> 1.10— it never actually calls hackney, so the constraint is dead weight, but it blocks resolution.httpoisonis overridden forgcs_signed_urlandpackmatic, which still declare 2.x.h2 ~> 0.11.0while hackney's ownwebtransportdep requiresh2 ~> 0.10.4, so they cannot resolve at all. 4.6.0 is the newest installable release.[http2, http1]), where 1.x was HTTP/1.1 only. Concurrent requests to one host then multiplex onto a single connection, so retiring that connection fails every in-flight request at once. Measured againstmix lightning.install_schemas(130 packages at concurrency 5): 27–35:closederrors under h2, 0 under[:http1], reproducibly.config/config.exspins[:http1]to keep the transport hackney 1.25 used — a security upgrade shouldn't smuggle in a protocol change. Worth adopting h2 later as its own piece of work.:invalid_stateis now retriable ininstall_schemas. hackney keeps a closing pooled connection alive briefly so requests that raced the checkout get an answer rather than crashing the caller. The comment inhackney_conn.erlsays it replies{:closed, _}, but the catch-all it falls through to replies:invalid_state, which wasn't in@retriable_reasons— so a package hitting that race was skipped after one attempt with no retry.mix_auditonly reads{:hex, ...}lock entries, so tzdata drops out ofmix deps.auditcoverage while we track master. It should move back to Hex as soon as a release carries the fix.config/test.exsdisables tzdata's autoupdater so the suite doesn't poll IANA on every CI run; dev and prod keep it on.deps/httpoisondialyzer filters are temporary. hackney 4 made a client handle a pid where it used to be a reference, butHTTPoison.AsyncResponse.t()still declaresid: reference(). Already fixed upstream in edgurgel/httpoison#511, merged 2026-07-05, just unreleased — 3.0.0 shipped 2026-06-14 and is still latest.AI Usage
Please disclose whether you've used AI anywhere in this PR (it's cool, we just
want to know!):
You can read more details in our
Responsible AI Policy
Pre-submission checklist
/reviewwith Claude Code)
(e.g.,
:owner,:admin,:editor,:viewer)