HydraIssues

Security: hydravoice binaries publicly exposed for 158 days via unsupervised http.server on neoremote:9999
open bug Priority: high Project: hydravoice Reporter: 31 Aug 2026 11:36

Description

Summary

An unsupervised python3 -m http.server was serving the hydravoice binary directory publicly to the internet on neoremote (195.201.27.157), port 9999, bound to 0.0.0.0. It had been running for 158 days. It was discovered on 2026-08-31 while diagnosing a full loss of SSH access to the host, and has now been stopped.

The exposure

python3 -m http.server 9999 --directory /home/claude-user/hydravoice/bin/

Process was orphaned to PID 1, with no systemd unit and no supervision. Directory listing was enabled (the default), so the following were publicly downloadable by anyone:

File Size Last modified
hydravoice 10598650 2026-03-22
hydravoice.exe 10791424 2026-03-25
hydravoice-player.exe 2850304 2026-03-25

Internet-wide scanners had found it. At the time of discovery there were 175 established connections from a broad spread of external IPs, including known scanner infrastructure (147.185.132.x / 147.185.133.x, 193.176.29.x, 69.5.169.x, 35.203.21x.x). Connection stats showed some had been idle for up to 43 days.

Impact

Availability. python3 -m http.server uses a thread per connection. The 175 stale scanner connections had each pinned a thread that never exited, on top of ~176 threads total for that one process. Combined with an 8 GB host that had no swap configured, memory pressure reached the point where sshd could no longer fork — SSH failed with Connection timed out during banner exchange while Hetzner still reported the server as running. Load average peaked around 69 on a 4-core box while the CPU sat 92-98% idle, which is the signature of blocked/leaked tasks rather than CPU contention.

Confidentiality. Production hydravoice binaries for Linux and Windows, plus the player, were retrievable by anyone who scanned the port. Assume they have been downloaded. Whether that matters depends on whether these binaries embed credentials, endpoints, or licensing material — that needs review.

Remediation already applied

  • The port 9999 server has been killed; nothing is listening on the public port now.
  • Unrelated host fixes made in the same pass: 4 GB swapfile added and persisted, journal/scratchpad/npm cleanup freeing ~4 GB disk, and OOM protection so sshd and long-lived sessions are not the first victims under memory pressure.

Follow-up needed

  1. Confirm nothing legitimately depended on this endpoint. It ran for 158 days, so if any device or pipeline fetched hydravoice builds from 195.201.27.157:9999, that fetch is now broken. Evidence suggests it did not — the connections were idle scanner traffic and the binaries were 5 months stale — but this should be confirmed rather than assumed.
  2. Review the exposed binaries for embedded secrets, internal endpoints, or signing material, and rotate anything sensitive.
  3. Provide a real distribution path if publishing hydravoice builds is an actual requirement, rather than an ad-hoc http.server — authenticated, supervised, and TLS-terminated.
  4. Prevent recurrence. Two cheap controls: a host firewall default-deny on inbound ports other than those explicitly published, and a periodic check that flags long-lived unsupervised listeners bound to 0.0.0.0.

Notes

neoremote currently has several other services bound to wildcard addresses (busybox httpd on 18123 serving a Claude scratchpad directory, hydramancer on 18099, hydraissue on 18085, cupsd on 631). These were not part of this incident and were left running, but the same firewall question applies to them.

Related hydravoice issues: #362, #366

Custom Fields

discovered
2026-08-31
exposure_days
158
host
neoremote (195.201.27.157)
port
9999
stale_connections_at_discovery
175
status_of_exposure
closed - process killed