Skip to content

kubefwd-v1.25.17

Choose a tag to compare

@github-actions github-actions released this 16 Oct 22:06
· 2 commits to master since this release
Immutable release. Only release title and notes can be modified.
v1.25.17
ceab4b4

kubefwd v1.25.17

Warning

Superseded by v1.25.18. Do not install this version.
v1.25.17 shipped with known vulnerabilities in golang.org/x/net. Five HTTP/2 advisories are reachable from kubefwd: GO-2026-6603, GO-2026-6610, GO-2026-6611, GO-2026-6612 and GO-2026-6617. It also has unreachable advisories in x/crypto and x/text. v1.25.18 fixes all of them and includes every fix below.

This release fixes three forwarding bugs:

  • A goroutine and memory leak on idle forwards across sleep and wake.
  • Forwards that kept pointing at the old port or pod after a Service was updated in place.
  • Forwards that flapped when the API server interrupted a pod watch.

It also fixes a vulnerability in golang.org/x/text that kubefwd's own code reaches. It moves to the Kubernetes 0.37 client libraries and brings in four months of dependency updates.

The fixes below are all included in v1.25.18. Install v1.25.18 instead.

Bug fixes

Idle forwards no longer leak goroutines and memory (#622, refs #614)

Reported by @avni-ef: memory grew from 74 MB to 1.48 GB over two days on a machine that slept and woke.

kubefwd keeps each forward's connection alive by pinging it every 30 seconds. Stopping the pinger sent a signal that gave up after 100 ms. If a ping was in flight on a connection that died during sleep, which can take up to 30 seconds, the signal was missed. That pinger then kept running against a dead connection forever, and every reconnect added another one.

Now:

  • Stopping is reliable. The stop signal is a closed channel, which a pinger sees even when it is busy at that moment, so stopping never times out.
  • Pinging stops on every exit path from a forward, including early errors.
  • A pinger also ends on its own when its connection closes.
  • A pinger never opens a new stream on a connection that is shutting down.

A regression test reproduces the leak against the old code. The approach comes from #619 by @AdamMagued.

The report also shows a second, smaller leak of SPDY connection goroutines. Its root cause is in the Kubernetes streaming library, not in kubefwd. This release makes it less likely to happen, and #614 stays open to track it.

In-place Service updates now rebuild forwards (#617, fixes #615)

Contributed and reported by @idan-rahamim-lendbuzz.

When a Service changed in place, kubefwd kept forwarding to the old target. This happened with a Helm upgrade that moved a port to a sidecar, a changed targetPort, or a changed selector. Before, kubefwd only noticed a change in the number of ports, and even then it resynced from its stale copy of the Service. The only fix was a restart.

Now:

  • Port or selector changes: kubefwd compares the Service's ports and selector, stops the affected forwards, waits for their cleanup to finish, and rebuilds them from the new spec. A targetPort change and a selector change that moves the Service to different pods both take effect within about a second.
  • Selector removed: the Service's forwards stop.
  • Selector added: a Service that previously had no selector, and was skipped, gets forwarded.
  • Status-only and metadata-only updates are still ignored.
  • TUI: shows a ServiceUpdated event for each rebuild.

Two related fixes come with it. A finishing forward no longer removes a replacement registered under the same key. Pod syncs are serialized, so a rebuild can't interleave with a reconnect or resync.

Tested on a KIND cluster against v1.25.16:

Check v1.25.16 v1.25.17
Initial forward pass pass
targetPort 5678 → 5679 still hits 5678 follows to 5679
Selector moved to a different deployment still hits the old pod follows to the new pod
/etc/hosts cleaned up on exit pass pass

A rebuild can give the Service a new loopback IP. The hostname follows it, but connections open during the rebuild are dropped.

Pod watch interruptions no longer flap forwards (#618, fixes #616)

Contributed and reported by @idan-rahamim-lendbuzz.

While waiting for a Pending pod to become Running, kubefwd used a single watch. If the API server sent an ERROR event or closed the stream, kubefwd treated that as a failed forward: it tore the forward down and backed off. On a busy cluster this made new forwards flap for about 25 seconds at startup.

Now an interrupted watch is retried after one second from a fresh read of the pod. The --timeout deadline and the stop signal work as before. The API server's error message is now logged, so the cause is visible.

Security

  • golang.org/x/text (GO-2026-5970), now 0.40.0 (#563). Invalid input could cause an infinite loop. This one was reachable from kubefwd's own code: the MCP HTTP client calls http.Client.Do, which reaches the vulnerable normalization code. It affects v1.25.16, which shipped x/text 0.34.0. Dependabot never flagged it; govulncheck found it.
  • golang.org/x/net (GO-2026-5942), now 0.57.0, and golang.org/x/crypto (GO-2026-5932), now 0.54.0 (#563 and later updates).
  • Integration-test module only, not part of the binary (#560, #563):
    • Moved from github.com/docker/docker to the moby/moby API and client modules by upgrading testcontainers-go to 0.43.0. This clears five Docker daemon advisories.
    • Bumped x/crypto, which clears 13 more alerts.
    • Fixed the integration module so it builds again.
  • Docs toolchain only (#560, #620): Pygments 2.20.0 (ReDoS) and urllib3 2.8.0 (GHSA-8988-9cw3-xx77, GHSA-vxq7-64xx-v4gw, GHSA-gh4c-6fx4-qh6g).

Dependency updates

Module v1.25.16 v1.25.17
k8s.io/api, apimachinery, client-go, cli-runtime, kubectl, streaming, component-base 0.36.2 0.37.1
github.com/modelcontextprotocol/go-sdk 1.6.1 1.8.0
charm.land/bubbletea/v2 2.0.7 2.0.9
charm.land/bubbles/v2 2.1.0 2.2.1
charm.land/lipgloss/v2 2.0.4 2.0.6
github.com/evertras/bubble-table 0.22.3 0.23.0
github.com/sirupsen/logrus 1.9.4 1.10.2
golang.org/x/sys 0.46.0 0.48.0
golang.org/x/net 0.51.0 0.57.0
golang.org/x/crypto 0.48.0 0.54.0
golang.org/x/text 0.34.0 0.40.0
golang.org/x/oauth2 0.35.0 0.36.0

Indirect dependencies were updated to match. Binaries are built with Go 1.26.9.

CI, build and supply chain

  • Build provenance: the release workflow now uses GitHub's native artifact attestation (actions/attest) for SLSA build provenance (#529, #537). This fixes the provenance step that failed in the v1.25.16 release run. Each archive and .mcpb bundle has a sigstore bundle, and each archive has an SBOM.

  • Action updates:

    • actions/checkout 7.0.0 (#530)
    • actions/setup-go 6.5.0 (#535)
    • actions/setup-python 6.3.0 (#534)
    • goreleaser/goreleaser-action 7.2.3 (#531)
    • golangci/golangci-lint-action 9.3.0 (#532)
    • docker/login-action 4.4.0 (#545)
    • docker/setup-buildx-action 4.2.0 (#543)
    • github/codeql-action 4.38.2
    • codecov/codecov-action 7.1.1
    • anchore/sbom-action 0.24.3

    All actions stay pinned to full commit SHAs (#553, #559, #579, #591, #602, #620).

Verify this release

gh attestation verify kubefwd_Darwin_arm64.tar.gz --repo txn2/kubefwd

Checksums are in kubefwd_checksums.txt, which also has a sigstore bundle.

Install / upgrade

# Homebrew (macOS / Linux)
brew install txn2/tap/kubefwd
brew upgrade kubefwd

# Docker
docker pull txn2/kubefwd:v1.25.17              # also :v1.25.17_alpine-3, :v1.25.17_ubuntu-24.04

# Or download a binary or package (deb, rpm, apk) for your platform from the assets below.

Run it (requires root for /etc/hosts and loopback aliases):

sudo -E kubefwd svc -n <namespace> --tui

Thanks

Full changelog: v1.25.16...v1.25.17