Summary
The HTTP accept loop spawns one Tokio task for every accepted TCP connection
and serves it with Hyper HTTP/1 without a global/per-IP concurrency limit or
explicit header-read/idle timeout.
Authentication is reached only after a complete request, so unauthenticated
clients can retain tasks and file descriptors with incomplete slow requests.
Observed on 88a5703496386465556d920dccf49512296c53d0 (current main).
Impact
A remote client can cause task/file-descriptor exhaustion and prevent
legitimate clients from connecting. A correctly configured reverse proxy may
mitigate this, but the shipped server and Compose setup do not enforce one.
Code evidence
server/src/main.rs:160-177 accepts each connection and immediately calls
runtime.spawn, with no semaphore or timeout around
http1::Builder::new().serve_connection(...).
Proof of concept
Against a disposable local instance, a slow-header test can be run with:
slowhttptest -H -c 1000 -r 100 -i 10 -s 8192 -u http://127.0.0.1:8080/vss/getObject
During the run, observe the server's open file descriptors/tasks grow while
the clients leave HTTP headers incomplete.
Suggested remediation
- Bound concurrent connections with a semaphore and return capacity promptly.
- Configure header-read and idle timeouts with a Hyper timer.
- Consider per-source limits and document required proxy limits.
Reported by Bitcoin Red Team.
Summary
The HTTP accept loop spawns one Tokio task for every accepted TCP connection
and serves it with Hyper HTTP/1 without a global/per-IP concurrency limit or
explicit header-read/idle timeout.
Authentication is reached only after a complete request, so unauthenticated
clients can retain tasks and file descriptors with incomplete slow requests.
Observed on
88a5703496386465556d920dccf49512296c53d0(currentmain).Impact
A remote client can cause task/file-descriptor exhaustion and prevent
legitimate clients from connecting. A correctly configured reverse proxy may
mitigate this, but the shipped server and Compose setup do not enforce one.
Code evidence
server/src/main.rs:160-177accepts each connection and immediately callsruntime.spawn, with no semaphore or timeout aroundhttp1::Builder::new().serve_connection(...).Proof of concept
Against a disposable local instance, a slow-header test can be run with:
slowhttptest -H -c 1000 -r 100 -i 10 -s 8192 -u http://127.0.0.1:8080/vss/getObjectDuring the run, observe the server's open file descriptors/tasks grow while
the clients leave HTTP headers incomplete.
Suggested remediation
Reported by Bitcoin Red Team.