Fix race condition in get_free_port by binding to localhost
What changed, and why it matters
This change fixes a small race condition in test helper code that picks a free network port. Previously the helper bound to all network interfaces ("any address"), which could briefly listen on an externally reachable address during automated tests. The patch restricts it to localhost only (127.0.0.1), reducing exposure. It is in test infrastructure, not the main wallet software users rely on, so real-world security impact is low.
No urgent action for end users; the change is in test code. Developers should ensure test harnesses run with this patch and consider replacing get_free_port() with fully deterministic port allocation (e.g., bind-then-fork, or let the OS assign and pass the fd) to eliminate the remaining TOCTOU window entirely.
Security signals we found
Binding transient test socket to all interfaces instead of localhost
Potential port squatting / race between port discovery and service startup
Test-only code path, not production wallet logic
Evidence from the diff
In test/test_device.py, get_free_port() creates a temporary TCP socket to discover an unused ephemeral port for a test bitcoind instance. The original s.bind((“”, 0)) binds to all IPv4 interfaces (0.0.0.0), meaning the transient listening socket could be reachable from the network during the brief window before it is closed and the port is reused by bitcoind. The patch changes the bind address to 127.0.0.1, limiting the transient listener to localhost and closing a potential race where another host (or a local attacker) could connect to or squat on the discovered port before the intended service starts.
Changed components
test/test_device.pyBitcoind test fixture helper get_free_port()Inspect captured patch +1 / −1
diff --git a/test/test_device.py b/test/test_device.py
index d22fdc3..abc6ef1 100644
--- a/test/test_device.py
+++ b/test/test_device.py
@@ -68,7 +68,7 @@ class Bitcoind():
def get_free_port():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind(("", 0))
+ s.bind(("127.0.0.1", 0))
s.listen(1)
port = s.getsockname()[1]
s.close()
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.