Scope: user-facing changes on branch ai-incoming (the unreleased 1.12 line, HEAD e0b639d) compared to master (310eec3 — released v1.11.7 927abde plus one dependency bump, no UX impact).
Date: 2026-07-02, revised 2026-07-17.
Method: three parallel code reviews (client surface, server/operator surface, tunnel/wire surface) plus manual verification of every load-bearing claim against the code. This revision re-verified each changed claim against current code.
Status: all four recommendations below were implemented on ai-incoming (commits 3c66f9b and c4038c3) — the §5 gaps are closed. The branch has since been rebased onto current master, with its Go-module and CI-action dependencies brought fully up to date (§7).
The branch is a large but well-behaved surface change. Measured against master, there are only three genuinely breaking changes for existing users, and the branch documents all of them — plus it retroactively documents the SOCKS ACL break that master already shipped in v1.11.7 with zero README coverage. The one remaining rough edge is a silent automation-facing change (exit codes), which the changelog calls out. The diagnosability gap flagged in the original review — ACL denials logging only at debug level — has since been fixed (they now log at info).
--authfile — already on master, branch adds the missing docsEnforcement (UserAddr() → "socks", channel-level ACL gate) shipped in v1.11.7 (927abde), so branch-vs-master this is not a new break — but today's released chisel has an undocumented breaking change: its README/--help say nothing about the socks token. The branch fixes that in five places (server help, client help, README auth section, SOCKS guide, 1.12 changelog) including the migration line "existing authfiles which should allow SOCKS5 must add an entry matching socks". This documentation is arguably the most valuable UX content on the branch.
The original review flagged a diagnosability gap here: a denied user's server-side trace was Debugf("Denied connection to socks (ACL)"), invisible without -v, making "socks stopped working after upgrade" the #1 anticipated support ticket. This is now fixed — commit 3c66f9b raised it to Infof("Denied connection to %s (ACL)", hostPort) (share/tunnel/tunnel_out_ssh.go:57), so operators see socks ACL denials at the default log level.
Master's verifyLegacyFingerprint used strings.HasPrefix, so --fingerprint a5:b3 matched any key with that MD5 prefix (~1-in-65k spoof risk). The branch requires the full 16-octet colon form (client/client.go:248). Affected users fail loudly at connect with Invalid fingerprint (...), and the preceding info line helpfully prints the correct SHA256 fingerprint to migrate to. SHA256 fingerprints were always exact-match — only MD5 stragglers with shorthand configs are affected. Documented in README Security, and the 1.12 changelog now lists it as breaking (added in c4038c3).
--auth without a colon is now a fatal startup error — branch-new, loudOn master, --auth nocolon silently degraded (server: user never registered → effectively no auth; client: empty credentials). That's a security footgun, and the branch turns it into invalid auth string, expected <user>:<pass> at startup on both sides. Anyone hit by this was already running something other than what they believed. Documented in README, and the 1.12 changelog now lists it as breaking (added in c4038c3).
--max-retry-count exhaustion: 0 → non-zero — branch-new, silent for automationclient_connect.go now returns connection attempts exhausted on give-up (ctx-cancel/Ctrl-C still exits 0). Correct behavior, but it's the one change scripts and Restart=on-failure units experience with no error message to notice — the semantics of $? just flip. It is in the 1.12 changelog, which is the right mitigation.
--min-retry-interval). Softer thundering-herd on server restarts; individual reconnects marginally slower.CHISEL_PING_TIMEOUT, default = keepalive interval, so ~50s at defaults vs 15–60 min of kernel retransmit limbo on master). Sleep/wake and NAT-timeout hangs become visible reconnects in logs. Old peers reply to pings, so mixed versions are fine.CHISEL_DIAL_TIMEOUT 30s). Apps see "connection refused/timeout" instead of master's instant-success-then-EOF. Strictly better UX, but tools that measured "connect success" will notice.shutdown(SHUT_WR) traverses the tunnel (share/cio/pipe.go), fixing netcat-style pipelines and rsync. Falls back to full-close against old peers — no hangs, just old behavior.CHISEL_SHUTDOWN_GRACE 5s, under docker's 10s default), second forces exit. Master died instantly on SIGTERM.Open (user=… addr=… remotes=…) / Close (… duration=…) and Login failed for user X (ip) — failed logins are finally fail2ban-able. Two side effects: log parsers keyed on the old debug Closed connection need updating, and tunnel endpoints now appear in default-level logs (mild privacy consideration for shipped logs).--auth user is pinned across reloads and wins name clashes; removed users lose new tunnels but established ones aren't cut (documented). Operators who habitually restart after edits will find edits now apply live..*-style files keep working but get noisy — the warning is doing its job, since unanchored patterns really do over-match.CHISEL_WS_READ_LIMIT, 0 disables) on both sides. Max legit SSH packet is ~35KB, so ~2× headroom; the only tail risk is a pathological config payload (thousands of remotes on one client), and the env knob is the escape hatch.CHISEL_UDP_DEADLINE 15s), so DNS-heavy exit nodes recover instead of wedging.BindRemotes failure now unbinds earlier listeners (no zombie ports); bad --keyfile errors no longer echo raw key material into logs; go install builds report real versions; 3000/UDP uppercase now parses.No compile-breaking signature changes in client, server, or share/.... Additive: client.Config.MinRetryInterval, Client.Ready(ctx), Tunnel.Ready, UserIndex.PinUser. Behavioral: NewServer returns errors where master called log.Fatal inside (a win for embedders), Remote.UserAddr() returns "socks" for forward-socks, L4Proto lowercases — only code depending on those exact outputs would notice.
Protocol string is unchanged (chisel-v3), and no handshake changes were found.
socks5:// proxy scheme is client-local.Strengths: breaking changes are stated as breaking, in the places users actually look (flag help, auth section, changelog); the env-var table surfaces a dozen previously undiscoverable knobs with sides and defaults (all verified against the code — PING_TIMEOUT, WS_READ_LIMIT, UDP_*, SHUTDOWN_GRACE, DIAL_TIMEOUT); the dead Heroku demo is replaced with a working fly.io recipe (linked example/fly.toml and example/reverse-tunneling-authenticated.md both exist); new TLS, CDN, and reverse-SOCKS-with-authfile guides fill real gaps; version-history typo (akp→apk) fixed. Several master help-text errors are corrected without behavior changes — verified that remote-host already defaulted to 127.0.0.1 in code (master's "0.0.0.0" doc was wrong) and --backend/--proxy were already aliases on master.
Gaps found at review time (all four have since been fixed — see §6):
-v.--fingerprint help said fingerprints "must be 44 characters containing a trailing equals" — contradicting the still-supported legacy MD5 colon form described in the Security section.PING_TIMEOUT "default: keepalive interval" didn't state what happens with --keepalive 0.3c66f9b (tunnel_out_ssh.go — denials now log Denied connection to <dest> (ACL) without -v).c4038c3.--fingerprint help text with the legacy-MD5 reality — help now states legacy MD5 fingerprints are accepted only in full 16-octet form. Implemented in c4038c3 (main.go + README help copy).c4038c3. The PING_TIMEOUT env-table row also now notes it is inert with --keepalive 0 (verified: the keepalive loop is skipped entirely at tunnel.go:93).Since the original review the branch was rebased onto current master (310eec3) and its dependencies brought fully current. These carry no user-facing behavior change — they matter for the security and compatibility posture:
golang.org/x/crypto 0.54.0, golang.org/x/net 0.57.0, golang.org/x/sync 0.22.0, github.com/fsnotify/fsnotify 1.10.1 (indirect x/sys 0.47.0, x/text 0.40.0). go build ./..., go vet ./..., and go mod verify all pass.actions/checkout v7, docker/setup-qemu-action v4, docker/setup-buildx-action v4, docker/login-action v4; docker/build-push-action was dropped by the goreleaser rework.Review produced 2026-07-02 by OJ (Claude Fable 5), revised 2026-07-17. Comparison basis: ai-incoming@e0b639d vs master@310eec3 in github.com/jpillora/chisel.