Watch
0
0
Fork
You've already forked hyperhive
0

hive-c0re: bound request lines on the agent and manager sockets

serve() read each request with read_line into an unbounded String, so
size checks such as the 4 KiB Send body limit ran only after the whole
line was buffered. Any process in an agent container can write to
/run/hive/mcp.sock, and one stream with no newline grew hive-c0re's heap
until the host OOM-killed it.

Read at most 16 MiB per line. The largest request a client sends is an
OperatorMsg from the agent web UI's /send, whose body axum's default
limit caps at 2 MiB (the gateway's nginx admits 10 MiB); JSON escaping
can roughly double that, and the cap is 4x the result. A longer line
gets a Response::Err, the same shape as the parse-error path, and the
connection is closed because the rest of the line is still unread.

The line is read as bytes and parsed with serde_json::from_slice, so a
line with invalid UTF-8 now gets a parse-error response instead of the
connection being dropped.

Closes #4718
This commit is contained in:
atlas 2026-09-26 00:15:22 +02:00 • committed by mara
commit 65a1f8d902

View file

@ -302,7 +302,7 @@ fn schedule_to_wire(s: crate::scheduled_prompts::Schedule) -> hive_sh4re::schedu
}
#[cfg(test)]
mod tests {
pub(super) mod tests {
use super::*;
fn target(name: &str) -> hive_sh4re::schedule::WireScheduleTarget {
@ -377,10 +377,10 @@ mod tests {
/// anybody's ancestor or descendant.
const STRANGER: &str = "requester-with-no-relations";
/// A real `Coordinator` over a throwaway sqlite dir. The schedule
/// A real `Coordinator` over a throwaway sqlite dir. The socket-server
/// handlers take `&Arc<Coordinator>`, so there is no lighter way in;
/// `open` touches nothing outside the db path it is handed.
fn coordinator() -> (tempfile::TempDir, Arc<Coordinator>) {
pub(in crate::socket_server) fn coordinator() -> (tempfile::TempDir, Arc<Coordinator>) {
let dir = tempfile::tempdir().expect("tempdir");
let coord = Coordinator::open(
&dir.path().join("broker.sqlite"),