goshs: SSH host key verification disabled, allowing transparent MITM of every tunnelled HTTP request
Date: 2026-05
Affected: go/goshs.de/goshs/v2
Attack vector: other
Category: vulnerability-disclosure
Severity: High
CWE: CWE-295
CWE-322
CVSS: 7.4 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N)

### Summary The `--tunnel` / `-t` flag opens an outbound SSH connection to `localhost.run:22` with `HostKeyCallback: ssh.InsecureIgnoreHostKey()`. The Go documentation for that function states verbatim: *"It should not be used for production code."* With the callback disabled the client accepts any host key the server presents, so an attacker who can intercept the operator's TCP connection to `localhost.run:22` (any router on the path, malicious local network, ARP/DNS spoof on the operator's LAN, BGP hijack, malicious VPN) can present their own SSH host key, terminate the SSH session locally, and proxy onward — sitting transparently in the middle of the tunnel. Because `localhost.run` does TLS termination at their end, the HTTP traffic on the SSH leg is plaintext, so the on-path attacker reads and rewrites every request and response in cleartext. The goshs operator gets no warning; the public URL works normally. ### Affected Code **File:** `tunnel/tunnel.go` ```go func Start(localIP string, localPort int) (*Tunnel, error) { config := &ssh.ClientConfig{ User: "nokey", Auth: []ssh.AuthMethod{ssh.Password("")}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), // accepts any server key Timeout: 10 * time.Second, BannerCallback: func(banner string) error { return nil }, } client, err := ssh.Dial("tcp", "localhost.run:22", config) ... } ``` There is no fallback verification — no `ssh.FixedHost


Mitigations:

Architectural layers (MAESTRO):