{"record":{"id":"ea43267688d0dd2f","repo":"gastownhall/beads","slug":"identity-oversized-reply","errorCode":null,"errorMessage":"identity: oversized reply","messagePattern":"identity: oversized reply","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/identity/control.go","lineNumber":69,"sourceCode":"\t}\n\tnonceBytes := make([]byte, identNonceBytes)\n\tif _, err := rand.Read(nonceBytes); err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: generate request nonce: %w\", err)\n\t}\n\tnonce := hex.EncodeToString(nonceBytes)\n\tif _, err := io.WriteString(conn, \"IDENT \"+secret+\" \"+nonce+\"\\n\"); err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: write request: %w\", err)\n\t}\n\n\tline, err := bufio.NewReader(io.LimitReader(conn, maxIdentReplyBytes+1)).ReadString('\\n')\n\tif errors.Is(err, io.EOF) && len(line) == 0 {\n\t\treturn nil, ErrIdentRefused\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: read reply: %w\", err)\n\t}\n\tif len(line) > maxIdentReplyBytes {\n\t\treturn nil, errors.New(\"identity: oversized reply\")\n\t}\n\n\tvar reply IdentReply\n\tif err := json.Unmarshal([]byte(line), &reply); err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: decode reply: %w\", err)\n\t}\n\tif err := VerifyIdentReply(reply, secret, nonce); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &reply, nil\n}\n\n// SignIdentReply authenticates reply for the nonce in an IDENT request.\n// The MAC covers the raw nonce bytes followed by canonical JSON for every\n// reply field except MAC.\nfunc SignIdentReply(reply IdentReply, secret, nonce string) (IdentReply, error) {\n\tnonceBytes, err := decodeIdentNonce(nonce)\n\tif err != nil {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/identity/control.go#L51-L87","documentation":"Identify reads a single newline-delimited JSON reply from the control connection and enforces a hard cap of maxIdentReplyBytes (4096). A reply longer than the cap is rejected outright — the peer is not speaking the identity protocol or is hostile, so no attempt is made to parse it.","triggerScenarios":"Calling Identify against a listener that answers the identity request with data exceeding 4096 bytes before the first newline — e.g. a misconfigured service, garbage/binary response, or an unauthenticated peer flooding the socket.","commonSituations":"Pointing identity discovery at the wrong socket (a different daemon that replies verbosely); a compromised or rogue process squatting on the control socket; protocol version mismatch producing large error payloads.","solutions":["Confirm the socket belongs to the managed proxy and speaks the identity protocol (correct version/schema)","Reject and re-dial; do not retry against the same peer without verifying its identity first","Cap reads client-side as well so a hostile peer cannot exhaust memory before this check","Audit who can connect to the control socket (filesystem permissions on the unix socket)"],"exampleFix":"// before\nreply, err := identity.Identify(conn, secret)\nif err != nil { log.Fatal(err) }\n// after\nreply, err := identity.Identify(conn, secret)\nif err != nil {\n    if strings.Contains(err.Error(), \"oversized reply\") { return ErrNotAProxyPeer } // wrong/hostile listener\n    return err\n}","handlingStrategy":"validation","validationCode":"// client-side cap: never read unbounded from the control socket\nlimited := io.LimitReader(conn, identity.MaxIdentReplyBytes+1)","typeGuard":"func isOversizedReply(err error) bool { return strings.Contains(err.Error(), \"oversized reply\") }","tryCatchPattern":"if err != nil {\n    if isOversizedReply(err) { conn.Close(); return ErrUntrustedPeer } // drop connection\n    return err\n}","preventionTips":["Point identity discovery only at the managed proxy's control socket","Restrict unix-socket permissions to the service user","Never retry Identify against a peer that sent oversized garbage","Keep protocol versions aligned between beads and the proxy"],"tags":["identity","ipc","protocol-violation","security"],"backgroundTag":"protocol-violation","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}