This is an automated email from the ASF dual-hosted git repository.

wwbmmm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new 9d5e5a7f Add threat model + security-model discoverability (AGENTS.md 
→ SECURITY.md → THREAT_MODEL.md) (#3324)
9d5e5a7f is described below

commit 9d5e5a7f263569fedc3257ffc679e8786a84b7ce
Author: Jarek Potiuk <[email protected]>
AuthorDate: Fri Jun 5 04:49:21 2026 +0200

    Add threat model + security-model discoverability (AGENTS.md → SECURITY.md 
→ THREAT_MODEL.md) (#3324)
    
    * Add threat model + security-model discoverability (AGENTS.md → 
SECURITY.md → THREAT_MODEL.md)
    
    Generated-by: Claude Code
    
    * THREAT_MODEL.md: renumber out-of-scope threats list to start at 1
    
    Per review (chenBright) — the "Threats explicitly out of scope" list was
    continuing the previous list's numbering (8-15); restart at 1-8.
    
    Generated-by: Claude Code
---
 AGENTS.md       |  27 +++
 SECURITY.md     |  13 ++
 THREAT_MODEL.md | 627 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 667 insertions(+)

diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 00000000..b0fde766
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,27 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for brpc
+
+This file is read by automated agents (security scanners, code
+analyzers, AI assistants) operating on this repository.
+
+## Security
+
+Security model: [SECURITY.md](./SECURITY.md)
+
+Agents that scan this repository should consult `SECURITY.md` and the
+threat model it links before reporting issues.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..ac8d16b9
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,13 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+`apache/brpc` follows the [Apache Software Foundation security 
process](https://www.apache.org/security/). Please report suspected
+vulnerabilities privately to `[email protected]`; do not open public
+GitHub issues or pull requests for security reports.
+
+## Threat Model
+
+What the project treats as in scope and out of scope, the security
+properties it provides and disclaims, the adversary model, and how
+findings are triaged are documented in [THREAT_MODEL.md](./THREAT_MODEL.md).
diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md
new file mode 100644
index 00000000..e3185076
--- /dev/null
+++ b/THREAT_MODEL.md
@@ -0,0 +1,627 @@
+# Apache bRPC — Threat Model (v1 draft)
+
+## §1 Header
+
+- **Project:** Apache bRPC (`apache/brpc`).
+- **Scope:** the `apache/brpc` repository only. The PMC confirmed on 
2026-05-20 that `apache/brpc-website` is out of scope for this engagement. This 
draft is first authored by the ASF Security Team and then reviewed by the PMC.
+- **Version binding:** based on `master` around 2026-05-21. Vulnerability 
reports should be triaged against the model for the corresponding version, not 
against `HEAD`; re-bind on each release.
+- **Authors and status:** drafted by the ASF Security Team (Glasswing 
pre-scan), revised by PMC member Weibing Wang. **DRAFT v1**
+- **Reporting entry point:** at drafting time, the repository had no 
`SECURITY.md`, and the Apache security project index listed only the generic 
`[email protected]` address. Until project-level disclosure documentation is 
published, report vulnerabilities to `[email protected]` per ASF policy.
+- **Provenance legend:**
+  - *(documented — source)*: from repository documentation, headers, gflags, 
source code, or Apache governance artifacts.
+  - *(inferred — Qn)*: inferred from code structure, general RPC security 
experience, or absence of a defense, with a corresponding question in §14.
+  - *(maintainer)*: not yet used in this draft; to be substituted after PMC 
confirmation.
+- **Draft confidence:** most factual descriptions in §1-§13 come from 
documentation and source code. Intent, default security posture, resource 
boundaries, the built-in service trust model, and vulnerability triage criteria 
still require confirmation in §14.
+- **bRPC overview:** bRPC is an embeddable C++ RPC framework that supports 
dispatching multiple protocols on the same port via content sniffing, including 
`baidu_std`, HTTP/1.x, HTTP/2/gRPC, Thrift, Redis, memcached, RTMP, Mongo, the 
nshead family, and others. It provides naming services, load balancers, 
optional TLS, bthread scheduling, and HTTP built-in admin services. bRPC is not 
a standalone daemon; downstream applications link `libbrpc` and start 
`brpc::Server` in-process.
+
+---
+
+## §2 Scope and intended use
+
+bRPC's primary uses are:
+
+1. Expose one or more `google::protobuf::Service` implementations on a TCP 
port, with multiple protocols sharing the same port.
+2. Act as a client `brpc::Channel` to access a single server or a cluster 
described by a naming service plus load balancer.
+3. Be embedded by a host application; deployment, TLS, network exposure, 
authentication, routing, and process lifecycle are the responsibility of the 
application or operator.
+4. Use built-in services such as `/status`, `/vars`, `/flags`, `/connections`, 
`/rpcz`, and `/health` for debugging and monitoring.
+5. Use bRPC as an HTTP/h2 server or client, including Restful URL mapping and 
JSON-to-Protobuf / Protobuf-to-JSON conversion.
+
+bRPC is not a secure-by-default managed service. Threats land in the runtime 
code linked by the application and in the built-in admin services the 
application chooses to expose.
+
+### Caller / actor roles
+
+- **Application developer:** defines `.proto` files, implements services, 
chooses protocols and ports, and calls clients. Trusted within the compile-time 
and configuration boundary.
+- **Operator:** runs the binary and configures ports, `internal_port`, TLS, 
gflags, naming services, rate limiting, and built-in services. Trusted for that 
instance.
+- **Client peer (RPC client):** sends bytes to a bRPC server. Untrusted by 
default; protocol sniffers must handle arbitrary input.
+- **Server peer:** the remote server that a bRPC client connects to. Response 
bytes are also untrusted.
+- **Naming-service backend:** `bns`, `file`, `consul`, `nacos`, DNS, and 
similar backends. Configured by the operator and treated by bRPC as trusted 
infrastructure.
+- **Built-in admin-service consumer:** a person or program accessing 
`/status`, `/flags`, `/rpcz`, and similar endpoints. Its trust level depends 
entirely on whether the operator places these endpoints on an internal network 
or disables them.
+
+### Component-family table
+
+| Family | Representative entry point | Touches outside the process? | In 
model? |
+| --- | --- | --- | --- |
+| **C++ runtime core** | `Server::Start`, `Channel::CallMethod`, `Socket`, 
`InputMessenger` | sockets, files, threads, TLS, optional RDMA | **In model** |
+| **Wire-protocol parsers** | `Parse*Message` | reads untrusted bytes from 
sockets | **In model**, highest priority |
+| **HTTP / h2 (+ gRPC) stack** | `HttpServerHandler`, `H2StreamContext`, `URI` 
| sockets, TLS, json2pb | **In model** |
+| **Built-in admin services** | `/status`, `/vars`, `/flags`, `/rpcz`, `/dir`, 
`/threads`, profiler, metrics | HTTP, `/proc`, filesystem, profiler | **In 
model**, depending on exposure |
+| **TLS / SSL layer** | `ServerSSLOptions`, `ChannelSSLOptions` | OpenSSL, 
certificate files | **In model** |
+| **Authentication hooks** | `Authenticator::VerifyCredential` | wire token | 
**In model**, policy is implemented by the application |
+| **Naming services** | `file://`, `http(s)://`, `consul://`, `nacos://`, 
`dns://` | files and network | **In model**, backend treated as trusted |
+| **Load balancers** | rr, wrr, random, la, consistent hashing | pure 
computation | **In model**, not a direct attack surface |
+| **Compression layer** | gzip/snappy/zlib/lz4 | CPU/memory | **In model** |
+| **RDMA transport** | `rdma://` | verbs API, pinned memory | **In model** 
only when enabled at build time and runtime |
+| **Coroutine bridge** | `usercode_in_coroutine` | scheduling | **In model** 
in non-default mode |
+| **bthread / butil / bvar** | scheduler, IOBuf, counters | threads, futex, 
files, `/proc` | **In model** |
+| **mcpack2pb / json2pb** | mcpack/JSON <-> pb | pure computation | **In 
model** on the corresponding protocol paths |
+| **Java / Python bindings** | JNI / pyBRPC | language bridge | currently 
unsupported; **Out of model** |
+| **tools / test / example / build / community / docs** | CLI, tests, 
examples, build, governance, docs | non-production runtime surface | **Out of 
model** |
+
+Wire-protocol parsers are the most important surface: they directly receive 
untrusted bytes, are implemented in C++, cover many protocols with different 
maturity levels, and multi-protocol sniffing can make every registered parser 
reachable from the same listening port. `enabled_protocols` can restrict the 
sniffing set, but its implementation details need maintainer confirmation.
+
+---
+
+## §3 Out of scope (explicit non-goals)
+
+The following scenarios or threats are not protected by the bRPC threat model. 
Matching reports are closed according to §13.
+
+### Use cases out of scope
+
+1. **A secure-by-default RPC endpoint.** bRPC provides components, not a 
`brpcd` with a strong default security posture.
+2. **A sandbox or process-isolation boundary.** Deserialization, business 
handlers, and the host application run in the same process.
+3. **Cryptographic primitives.** TLS security comes from OpenSSL; bRPC only 
wraps and configures it.
+4. **An application field-validation framework.** bRPC validates wire framing, 
not semantic fields such as email addresses, IDs, or business ranges.
+5. **A complete replacement for authenticated transport.** Bare `baidu_std`, 
HTTP, Thrift, Redis, and similar protocols have no default authentication; 
`Authenticator` and mTLS require explicit configuration.
+6. **A general HTML/JSON rendering security surface.** Escaping in application 
HTTP handlers is the application's responsibility.
+7. **A general file server.** `/dir` is disabled by default and is not modeled 
as a production file-serving feature.
+8. **Exposing built-in services to the public internet.** bRPC built-in 
services should only be exposed to trusted internal consumers.
+
+### Threats explicitly out of scope
+
+1. Attackers who control the calling process, can read/write process memory, 
or can call arbitrary bRPC APIs.
+2. Attackers who control the compiler, dependencies, build environment, or 
supply chain.
+3. Side channels such as timing, cache, power, and RowHammer.
+4. Raw socket-layer DoS: SYN flood, slowloris, half-open connection 
exhaustion, and kernel table exhaustion.
+5. Resource exhaustion in `bvar`/`bthread`/`butil` caused purely by in-process 
call patterns.
+6. Performance loss caused by an operator intentionally enabling expensive 
tracing/profiling.
+7. Compromise of the naming-service backend; bRPC trusts the backend 
configured by the operator.
+8. Vulnerabilities in application handlers, such as SQL injection or missing 
business authorization.
+
+### Code shipped in the repo but out of scope
+
+`test/`, `example/`, `tools/`, build and packaging files, `community/`, 
`docs/`, and `apache/brpc-website` are not modeled as production runtime 
surfaces. The core boundary is the runtime, parsers, transports, built-in 
services, and support libraries under `src/`.
+
+---
+
+## §4 Trust boundaries and data flow
+
+bRPC has four main trust boundaries: three on the network surface and one on 
the operator configuration and naming-service surface.
+
+### Boundary 1 — the wire (server side, business RPC)
+
+Server-side socket bytes are untrusted by default:
+
+```text
+socket bytes
+  -> Acceptor / Socket
+  -> InputMessenger::CutInputMessage
+     -> try registered protocol parsers one by one
+     -> check whether declared body size exceeds -max_body_size
+  -> protocol message structure
+  -> protobuf / json2pb / mcpack2pb / other decoder
+  -> Service::Method(controller, request, response, done)
+```
+
+The trust transition occurs when the framework calls the user's 
`Service::Method`. Crashes or memory corruption reachable from the wire in 
parsers, decoders, compression, and TLS handshake are in model. How the 
business handler processes `Request` is the application's responsibility.
+
+All protocol parsers are enabled by default. `ServerOptions.enabled_protocols` 
can restrict the protocol sniffing set.
+
+### Boundary 2 — the wire (server side, built-in admin services)
+
+HTTP/h2 requests on the same listening port may be routed to built-in 
services. `internal_port` can move built-in services to a separate port, and 
`has_builtin_services=false` can disable them entirely. `/dir` and `/threads` 
are disabled by default; other built-in services are enabled by default when 
`has_builtin_services=true`.
+
+Model posture: built-in services are treated as an operator-trusted surface 
when placed on an internal port or protected by firewall. If exposed to the 
public internet, they become a major risk surface. Specific triage depends on 
Q46/Q50 in §14.
+
+Even when built-in services are only served internally, they still need to 
avoid severe attacks such as command injection or denial of service. However, 
modifying gflags, enabling rpcz, profiling, and similar operations through 
built-in services can affect business logic or program performance; those 
effects are normal use and are not security vulnerabilities.
+
+### Boundary 3 — the wire (client side)
+
+A bRPC client deserializes server responses through paths symmetric to the 
server side: untrusted bytes enter parsers and decoders before being handed to 
the application. Parser/decoder vulnerabilities triggered by malicious server 
responses are in model.
+
+### Boundary 4 — the operator config + naming-service backend
+
+`ServerOptions`, `ChannelOptions`, gflags, flagfiles, TLS file paths, and 
naming-service URIs are supplied by the operator and are trusted. Server lists 
returned by naming services are also treated as trusted infrastructure. Backend 
compromise is out of scope, but crashes in reply parsers on malformed input 
remain in model.
+
+### Reachability preconditions per family
+
+- Parser issues are in model only when reachable from Boundary 1/3; opt-in 
protocols require operator enablement.
+- Built-in services are triaged according to the Boundary 2 exposure rules.
+- TLS issues are inside the network surface; OpenSSL CVEs are handled as 
external dependency issues.
+- Compression, json2pb, and mcpack2pb are in model when reachable from 
attacker input.
+- RDMA and coroutine paths are modeled only when explicitly enabled or loaded.
+
+### Data not crossing a boundary
+
+Purely internal scheduler queues, in-process `bvar` counters, internal `IOBuf` 
lifetimes, `socket_map` lifetimes, Wireshark dissectors under `tools/`, and 
similar paths are not trust transitions.
+
+---
+
+## §5 Assumptions about the environment
+
+bRPC is a C++ library that normally runs on Linux/macOS with POSIX sockets, 
OpenSSL, and a C++ toolchain.
+
+### OS / runtime / hardware
+
+- Linux and macOS are supported; Windows is not included in the security 
support scope for now.
+- A C++11 or newer toolchain is required.
+- POSIX sockets and Linux epoll or macOS kqueue are required.
+- TLS depends on OpenSSL; risks from old OpenSSL versions are managed by the 
operator.
+- gflags, protobuf, and leveldb are regular dependencies; tcmalloc/gperftools 
is optional.
+
+### Concurrency
+
+- bthread is an M:N scheduler; the number of worker pthreads depends on CPU 
count or configuration.
+- `ServerOptions.num_threads` is a global worker-count hint, not hard 
isolation for one server.
+- bthread-local state may be reused; user destructors must be reentrant.
+- `-usercode_in_pthread` moves user code to pthreads and changes concurrency 
and queuing semantics.
+
+### Memory model
+
+bRPC is memory-unsafe C++. All `Parse*Message`, `Read*`, `Decompress*`, 
JSON/mcpack/protobuf decoder paths are candidate surfaces for OOB access, UAF, 
double-free, integer overflow, and stack overflow. `-max_body_size` is the key 
outer cap; the model depends on parsers correctly checking lengths and avoiding 
signed/unsigned overflow.
+
+### Time / clock
+
+bRPC uses `gettimeofday`, `clock_gettime`, `cpuwide_time_us`, and similar 
clocks. Resistance to timing side channels is not a goal.
+
+### Filesystem / network / peripherals
+
+bRPC opens TCP/Unix sockets, pid files, TLS cert/key files, naming-service 
files, profile output, rpc dumps, and reads `/proc/*` for bvar. It also sets 
normal socket options such as keepalive, `SO_REUSEPORT`, and `TCP_USER_TIMEOUT`.
+
+### What bRPC does *not* do to its host (negative-claim inventory)
+
+By default it does not install signal handlers. Normal operation does not fork 
child processes unless a profiler endpoint is triggered. It reads limited 
environment variables and gflags. First SSL use initializes OpenSSL global 
state. Logs go to stdout/stderr or glog. It does not modify locale or FPU 
state. `fork without exec` must happen before bRPC initialization.
+
+---
+
+## §5a Build-time and configuration variants
+
+bRPC's security boundary is affected by build options, gflags, 
`ServerOptions`, `ChannelOptions`, and SSL options.
+
+### Build-time options that change the security envelope
+
+| Knob / flag | Default | Effect on model |
+| --- | --- | --- |
+| `WITH_THRIFT` | off | makes compiling and enabling the Thrift parser 
possible |
+| `WITH_GLOG` | off | changes the logging backend; not critical |
+| `WITH_RDMA` | off | introduces RDMA transport and pinned memory |
+| `WITH_MESALINK` | off | OpenSSL replacement implementation |
+| `BUILD_UNIT_TESTS` | off | builds tests, out of model |
+
+*Note: the table above is only an example, not a complete list. Analyze the 
latest code for details.*
+
+### Runtime gflags that change the security envelope
+
+| Flag / option | Default | Effect | Maintainer stance |
+| --- | --- | --- | --- |
+| `-max_body_size` | 64 MiB | global body cap for all protocols; protobuf's 
internal cap is lifted to `INT_MAX` | critical |
+| `-enable_dir_service` | false | `/dir` reads files | dangerous when enabled |
+| `-enable_threads_service` | false | `/threads` dumps stacks | dangerous when 
enabled |
+| `-immutable_flags` | false | `/flags` can modify reloadable gflags | safer 
when enabled |
+| `-usercode_in_pthread` | false | changes the thread model for user code | 
changes concurrency semantics and may cause deadlocks |
+| `ServerOptions.has_builtin_services` | true | global switch for built-in 
services | critical |
+| `ServerOptions.internal_port` | -1 | built-in services are on the main port 
by default | critical; safer when set |
+
+*Note: the table above is only an example, not a complete list. Analyze the 
latest code for details.*
+
+### Insecure-default summary (the §13 routing question)
+
+Defaults triaged by the PMC:
+
+1. `-max_body_size=64 MiB` is the production default.
+2. `has_builtin_services=false` or `internal_port!=-1` is operator 
responsibility.
+3. The combination of `-immutable_flags=false` and reachable `/flags` is 
acceptable.
+4. `ChannelSSLOptions.verify.verify_mode=NOT_SET`, causing client TLS not to 
verify the server certificate, is acceptable.
+5. `ChannelSSLOptions.protocols` including TLS 1.0/1.1 is acceptable.
+6. `force_ssl=false`, causing a TLS-configured port to still accept plaintext, 
is acceptable.
+7. `/dir` and `/threads` are disabled by default. If an operator enables them 
and exposes them publicly, treat that as a dangerous non-default configuration.
+
+*Note: the table above is only an example, not a complete list. Analyze the 
latest code for details.*
+
+---
+
+## §6 Assumptions about inputs
+
+bRPC receives three classes of input: socket bytes, in-process API parameters, 
and operator configuration. Boundary 1/3 wire bytes are the highest risk.
+
+### Per-parameter trust table
+
+| Component / function | Parameter | Attacker-controllable? | Caller / 
operator must enforce |
+| --- | --- | --- | --- |
+| `InputMessenger::CutInputMessage` | initial connection bytes | yes | sniffer 
must defend against arbitrary bytes |
+| `ParseRpcMessage` | PRPC header, `RpcMeta`, payload | yes | 
`-max_body_size`, `meta_size <= body_size` |
+| `ParseHttpMessage` | method, URI, headers, body | yes | HTTP grammar, body 
cap |
+| `ParseH2Message` | frame, HPACK headers, SETTINGS | yes | 
frame/header/HPACK/SETTINGS caps |
+| Redis / memcache / Thrift / Mongo / nshead parsers, etc. | declared length, 
frame, body | yes | must be uniformly constrained by `-max_body_size` or 
protocol caps |
+| RTMP / AMF | chunk stream, AMF object | yes | chunk and nesting caps |
+| `json2pb::JsonToProtoMessage` | HTTP JSON body | yes | UTF-8, depth, 
repeated-field expansion |
+| `mcpack2pb` | mcpack body | yes | depth and size caps |
+| `Decompress` | compressed payload | yes | bRPC currently does not guarantee 
a decompressed-size cap; decompression may fail |
+| TLS handshake | cert, SNI, ALPN | yes | operator configures verify, SNI, 
ALPN |
+| `Authenticator::VerifyCredential` | credential, client_addr | yes; more 
obvious when header IP is enabled | application implements authentication; 
operator protects proxy boundary |
+| Built-in `/flags` | gflag value | yes if reachable | hide built-ins or set 
`-immutable_flags=true` |
+| Built-in `/dir` | path | yes if enabled | do not enable on public internet |
+| Built-in profiler | `seconds` and similar parameters | yes if reachable | 
hide built-ins and limit profiling cost |
+| `ServerOptions` / `ChannelOptions` / gflags | configuration values | no | 
operator trusted |
+| Naming service reply | backend response | trusted by transitivity | parser 
should still tolerate malformed replies |
+
+### Size, shape, rate
+
+- `-max_body_size=64 MiB` is the global message cap; there is no unified 
per-method or per-protocol cap.
+- The cap for unconsumed streaming RPC bytes is 
`-socket_max_streams_unconsumed_bytes`; default 0 means unlimited.
+- Pending write buffers per socket are limited by 
`-socket_max_unwritten_bytes`.
+- `max_concurrency` limits in-flight requests, not connection count; built-in 
services are not constrained by this option.
+- `idle_timeout_sec` is disabled by default; connection count and slowloris 
are mainly handled by operators / load balancers.
+- Protobuf has a recursion limit; JSON, mcpack, and AMF depth limits need 
confirmation.
+- The framework has no general rate limiting.
+
+---
+
+## §7 Adversary model
+
+### Primary adversary — the wire peer
+
+The primary attacker is the socket peer, which can send arbitrary bytes, 
confuse inputs across protocols, declare large lengths, construct compression 
bombs, trigger parser bugs, or make a client parse malicious server responses. 
Goals include crashes, memory/CPU exhaustion, OOB read/write, framing bypass, 
arbitrary command execution, authentication bypass, abuse of reachable built-in 
services, modification of reloadable gflags, and reading information through 
`/dir`.
+
+### Secondary adversary — the authenticated peer
+
+A peer that passes `Authenticator` is still untrusted at the parser layer. 
Authentication only narrows the attacker set; it does not change the peer's 
ability to send bytes.
+
+### Tertiary adversary — the HTTP-built-in-services consumer
+
+When `internal_port < 0` and `has_builtin_services=true`, any HTTP client that 
can reach the listening port may access `/status`, `/vars`, `/flags`, profiler, 
metrics, and similar endpoints. Final triage depends on Q46/Q50.
+
+### Out-of-scope adversaries
+
+In-process attackers, local side-channel attackers, attackers controlling 
`ServerOptions`/`ChannelOptions`, attackers controlling naming-service 
backends, build-chain attackers, and attacks that depend on the operator 
failing to harden network boundaries are not objects that bRPC itself promises 
to defend against.
+
+### Adversary capabilities by transport
+
+- **Plain TCP:** full wire control, no default authentication or encryption.
+- **TLS:** provides encryption, but client/server certificate verification and 
TLS-only behavior require operator configuration.
+- **RDMA:** modeled only when enabled; risks come from the verbs API and 
memory regions.
+- **Unix domain socket:** if supported, the trust model is similar to TCP, 
with socket file permissions managed by the operator.
+
+---
+
+## §8 Security properties the project provides
+
+### Memory and process-safety properties
+
+**P1. Under configured caps, valid wire input should not cause memory 
corruption.**  
+Any OOB access, UAF, double-free, or heap corruption in a parser, decoder, 
decompressor, TLS path, or built-in handler reachable from Boundary 1/3 is a 
high/critical issue.
+
+**P2. Bounded recursive structures should not cause stack overflow.**  
+Protobuf, JSON, AMF, mcpack, and similar decoders should reject excessively 
deep input before exhausting the stack.
+
+### Wire-format properties
+
+**P3. Multi-protocol sniffing should be conservative.**  
+When a parser returns `TRY_OTHERS`, it should not consume bytes; the same 
frame should not be taken over by the wrong parser.
+
+**P4. `-max_body_size` should be enforced.**  
+Parsers with declared lengths should reject and close the connection when the 
cap is exceeded; they should not allocate oversized memory first.
+
+### TLS / transport-security properties (when enabled)
+
+**P5. With SSL correctly configured and OpenSSL secure, TLS provides 
confidentiality and integrity.**
+
+**P6. The server rejects SSLv3 by default.**
+
+**P7. SNI can be used for certificate selection; fallback behavior on no match 
is controlled by `strict_sni`.**
+
+**P8. ALPN selection should be limited to `ServerSSLOptions.alpns`.**
+
+### Resource-bound properties
+
+**P9. Single-message memory use should be bounded by `-max_body_size`.**  
+Linear constant-factor overhead is acceptable; superlinear expansion or 
allocations that bypass the cap should be treated as bugs. See §9 D5 for 
decompression expansion.
+
+**P10. Per-socket unwritten buffers should be limited by 
`-socket_max_unwritten_bytes`.**
+
+**P11. Server/method concurrency caps should take effect when configured by 
the operator.**
+
+### Concurrency properties
+
+**P12. The framework's own cross-connection state should be thread-safe.** 
Synchronization of shared state in user handlers is the user's responsibility.
+
+**P13. `Channel::CallMethod` may be called across threads; `Channel::Init()` 
is not guaranteed to be thread-safe.**
+
+### Built-in admin-service properties (conditional on operator exposure)
+
+**P14. Built-in services should be protected by `has_builtin_services`, 
`internal_port`, or network boundaries.**
+
+**P15. `/dir` and `/threads` are disabled by default.**
+
+---
+
+## §9 Security properties the project does *not* provide
+
+### Disclaimed properties (downstream's job, not bRPC's)
+
+**D1.** Bare protocols do not have default peer authentication; 
`Authenticator` authenticates per connection, not per request.  
+**D2.** No application-layer authorization is provided; RBAC, ACLs, scopes, 
and rate limits are implemented by the application or `Interceptor`.  
+**D3.** When `-http_header_of_user_ip` is enabled, bRPC does not defend 
against attacker-forged headers; trusted proxies and firewalls must enforce the 
boundary.  
+**D4.** Without a configured cap, streaming does not defend against unlimited 
growth of unconsumed stream data.  
+**D5.** bRPC does not guarantee a decompressed-output size cap. Decompression 
failure is allowed, but crashes or memory boundary violations are not.  
+**D6.** bRPC does not guarantee a cap on decoded JSON/repeated-field size. 
Decode failure is allowed, but crashes or memory boundary violations are not.  
+**D7.** h2/HPACK bomb, CONTINUATION flood, and PING flood defenses are 
currently missing and should preferably be added.  
+**D8.** No constant-time guarantee is provided.  
+**D9.** OpenSSL weaknesses and default TLS version choices are managed by the 
operator.  
+**D10.** No anti-replay is provided; request/sequence IDs are only used for 
request/response matching.  
+**D11.** There is no confidentiality without TLS.  
+**D12.** bRPC does not defend against socket-layer connection floods or 
slowloris.  
+**D13.** When built-ins are exposed and `-immutable_flags=false`, bRPC does 
not defend against `/flags` modifying reloadable gflags.  
+**D14.** When built-ins are reachable, bRPC does not defend against 
information disclosure from `/status`, `/vars`, `/connections`, `/rpcz`, and 
similar endpoints.  
+**D15.** When built-ins are reachable, bRPC does not defend against CPU/IO 
cost from profiler endpoints.  
+**D16.** When `internal_port=-1`, user services and built-in services on the 
same port are not isolated.  
+**D17.** Cross-protocol confusion from the multi-protocol sniffer is a parser 
issue the framework must defend against, but the risk of not restricting the 
protocol set is the operator's responsibility.  
+**D18.** Pathological protobuf input under protobuf `TotalBytesLimit=INT_MAX` 
has no additional framework cap.  
+**D19.** When `force_ssl=false`, a TLS-configured port still accepts plaintext.
+
+### False-friend properties
+
+**F1.** `has_builtin_services=true` is an administrative surface, not just 
harmless debug pages.  
+**F2.** `Authenticator::VerifyCredential` runs once per connection, not once 
per request.  
+**F3.** `force_ssl=false` means the same port accepts both SSL and non-SSL.  
+**F4.** `Controller::remote_side()` may be affected by 
`-http_header_of_user_ip`.  
+**F5.** `verify_depth=0` means verification is disabled, not strict 
verification.  
+**F6.** `Authenticator` does not cover all protocols by default.  
+**F7.** `strict_sni=false` means an unknown SNI falls back to the default 
certificate.  
+**F8.** `-max_body_size` does not limit decompressed size, decoded JSON size, 
or protobuf's internal cap.  
+**F9.** The LZ4 enum and documented support status are not fully aligned and 
need confirmation.
+
+### Well-known attack classes left to the caller
+
+Compression bombs, JSON/repeated-field expansion, HPACK bombs, TLS compression 
oracles, TLS downgrade, authentication brute force, `/flags` weaponization, 
slow decoder DoS, HTTP request smuggling, cross-protocol confusion, and 
naming-service spoofing. Except for parser memory safety and explicit claims, 
most of these are mitigated by the operator or application.
+
+---
+
+## §10 Downstream responsibilities
+
+### Application developer responsibilities
+
+1. Pin the bRPC version and evaluate against that version's model.
+2. Treat all deserialized fields as untrusted application input and perform 
business-semantic validation.
+3. Implement `Authenticator` when identity is required, remembering that it 
authenticates per connection.
+4. Implement `Interceptor` or handler checks when per-request authorization is 
required.
+5. Do not call `Channel::Init()` concurrently across threads; `CallMethod()` 
is the thread-safe path.
+6. Do not cache gflag values long-term when running with reloadable flags.
+7. Do not use `assert` for security checks.
+
+### Operator responsibilities
+
+8. Hide built-in services on public ports: set `internal_port`, set 
`has_builtin_services=false`, or use a firewall.
+9. Keep `-enable_dir_service=false` and `-enable_threads_service=false` on 
public ports.
+10. Unless truly needed, set `-immutable_flags=true` or ensure `/flags` is 
reachable only by trusted operators.
+11. Configure TLS: server certificate, client verification, removal of TLS 
1.0/1.1, and `force_ssl=true` when needed.
+12. Set `max_concurrency`, per-method concurrency, `idle_timeout_sec`, and 
streaming caps.
+13. When enabling `-http_header_of_user_ip`, allow only trusted proxies to 
access the backend port.
+14. Do not run bRPC processes as root.
+15. Use escaping when application HTTP handlers output HTML.
+16. Put public endpoints behind a load balancer / reverse proxy for 
connection-rate control, slowloris handling, and L7 hardening.
+17. Track OpenSSL patches and rotate TLS material separately.
+18. If compression is enabled, limit decompressed size at the application 
layer or sidecar.
+19. Use `enabled_protocols` to expose only required protocols.
+20. Choose trusted naming-service backends and protect permissions on 
flagfiles, cert/key files, and pid files.
+
+### Both
+
+21. Re-read and revise this model on each major bRPC upgrade or whenever a §12 
condition occurs.
+
+---
+
+## §11 Known misuse patterns
+
+**M1.** Exposing a server with default `has_builtin_services=true` and 
`internal_port=-1` to the public internet.  
+**M2.** Treating `Authenticator` as per-request authentication.  
+**M3.** Enabling `-http_header_of_user_ip` while allowing clients to bypass 
the trusted proxy and connect directly.  
+**M4.** Calling `Channel::Init()` from multiple threads.  
+**M5.** Using `assert` for security checks.  
+**M6.** Running bRPC as root.  
+**M7.** Configuring SSL but forgetting `force_ssl=true`, leaving plaintext 
available.  
+**M8.** Using plaintext protocols across trust boundaries.  
+**M9.** Setting `-max_body_size` very large and assuming it will not affect 
memory.  
+**M10.** Assuming compressed output size is limited by the framework.  
+**M11.** Enabling `/dir` or `/threads` on the public internet.  
+**M12.** Enabling nshead/nova/public/nshead_mcpack and forgetting the sniffer 
will try these parsers.  
+**M13.** Treating sequence/correlation IDs as nonces.  
+**M14.** Exposing `/flags` while keeping `-immutable_flags=false`.  
+**M15.** Not revalidating `auth_context()` or downstream identity information. 
 
+**M16.** Combining `-usercode_in_pthread` with high concurrency without 
setting `max_concurrency`.  
+**M17.** Using an untrusted naming service while client TLS does not verify 
the server certificate.  
+**M18.** Exposing profiler endpoints to the public internet.  
+**M19.** Enabling `/rpcz` on traffic containing sensitive request fields.  
+**M20.** Enabling RDMA and exposing it to untrusted peers.
+
+---
+
+## §11a Known non-findings (recurring false positives)
+
+**N1.** A parser reading length and checking it with `FLAGS_max_body_size` is 
by design; it is an issue only if a parser truly skips the check.  
+**N2.** ~~Decompression has no decompressed-size cap, per §9 D5.~~  
+**N3.** Built-in services expose internal information; operators should hide 
them.  
+**N4.** `/flags` modifying reloadable gflags without authentication is pending 
Q46.  
+**N5.** `/dir` reads files: disabled by default; enabling it is a dangerous 
non-default configuration.  
+**N6.** `/threads` dumps stacks: disabled by default.  
+**N7.** bvar reading `/proc/loadavg` and `/proc/stat` is by design.  
+**N8.** Client TLS includes TLS 1.0/1.1 by default; triage pending Q56.  
+**N9.** Client TLS does not verify server certificates by default; triage 
pending Q57.  
+**N10.** `force_ssl=false` allowing plaintext is documented behavior.  
+**N11.** `Authenticator` running once per connection is documented behavior.  
+**N12.** Issues in test/example/tools/build/community are out of model.  
+**N13.** Hard-coded certificates under `test/` are out of model.  
+**N14.** HTTP Basic credentials in plaintext are a consequence of the operator 
choosing plaintext transport.  
+**N15.** MD5/SHA-1 used for load-balancer hash distribution is not 
cryptographic use.  
+**N16.** Wire-reachable integer overflow/OOB is a valid vulnerability class 
and should not be mechanically closed.  
+**N17.** `session_local_data_factory` lifetime is guaranteed by the user as 
required by documentation.  
+**N18.** The bthread keytable pool retaining objects is a reuse design.  
+**N19.** `Channel.Init()` being non-thread-safe is documented behavior.  
+**N20.** Runtime certificate add/delete/modify concurrency safety is judged 
case by case and needs maintainer confirmation.  
+**N21.** Built-ins being handled on the main port is default behavior; triage 
pending Q50.  
+**N22.** The sniffer trying multiple parsers on unknown bytes is by design.  
+**N23.** A fuzz crash in an opt-in parser can still be `VALID` when the path 
is enabled.  
+**N24.** Protobuf `TotalBytesLimit=INT_MAX` is documented design; the outer 
layer relies on `-max_body_size`.  
+**N25.** Naming-service backend replies are trusted.  
+**N26.** Triage for crashes on malformed DNS/consul/nacos replies must 
distinguish backend compromise from parser hardening.  
+**N27.** Brute-force authentication using many short connections is 
rate-limited by the operator.  
+**N28.** `/rpcz` may expose sampled request information; this is a design risk 
after enabling it.  
+**N29.** OpenSSL CVEs are not bRPC CVEs, but they affect deployments.  
+**N30.** `fork without exec` after bRPC initialization is unsupported.
+
+---
+
+## §12 Conditions that would change this model
+
+The following changes should trigger model revision:
+
+1. A new wire protocol parser or sniffer registration.
+2. A new built-in admin service, especially one with write capability.
+3. Changes to security-relevant defaults in §5a: `-max_body_size`, streaming 
caps, `-immutable_flags`, built-in defaults, `force_ssl`, TLS verification, TLS 
protocols, and so on.
+4. An opt-in protocol becoming enabled by default.
+5. Adding a decompressed-size cap.
+6. Adding h2/HPACK bomb defenses.
+7. Adding a per-request authentication mode.
+8. Adding `SECURITY.md` or a project security page to the repository.
+9. The PMC publishing a security policy.
+10. A new CVE class that cannot be triaged under §13.
+
+Vulnerabilities should be triaged against the model in effect for the affected 
version, not against the latest `HEAD`.
+
+---
+
+## §13 Triage dispositions
+
+| Disposition | Meaning | Licensed by |
+| --- | --- | --- |
+| `VALID` | violates a property claimed in §8, with attacker, input, and 
component all in model | §8, §6, §7 |
+| `VALID-HARDENING` | does not violate an existing claim, but the API easily 
leads to §11 misuse and the project may choose to harden it | §11 |
+| `OUT-OF-MODEL: trusted-input` | requires controlling configuration or 
objects marked trusted by the model | §6 |
+| `OUT-OF-MODEL: adversary-not-in-scope` | requires attacker capabilities 
excluded by the model | §7, §3 |
+| `OUT-OF-MODEL: unsupported-component` | located in out-of-scope components 
such as test/tools/example/build/community/docs | §3 |
+| `OUT-OF-MODEL: non-default-build` | appears only under dangerous or 
non-default configuration | §5a |
+| `BY-DESIGN: property-disclaimed` | belongs to a property explicitly 
disclaimed in §9 | §9 |
+| `KNOWN-NON-FINDING` | matches a recurring false-positive pattern in §11a | 
§11a |
+| `MODEL-GAP` | cannot be classified and requires model revision | §12 |
+
+### Worked routing examples
+
+- `Parse*Message` OOB write: `VALID`.
+- Private key leak under `test/`: `OUT-OF-MODEL: unsupported-component`.
+- Client TLS not verifying server certificates by default: `BY-DESIGN`.
+- Remote access to `/flags/max_body_size?setvalue=0`: operator responsibility.
+- `/dir?path=/etc/passwd`: if it requires `-enable_dir_service=true`, 
`OUT-OF-MODEL: non-default-build`.
+- A small gzip payload decompressing to huge output and causing OOM: `VALID`.
+- h2 HPACK bomb: if defenses are missing and reachable, potentially `VALID`.
+- Hostile consul backend redirecting a client: `OUT-OF-MODEL: 
adversary-not-in-scope`; malformed reply crashes can be judged separately.
+- OpenSSL CVE: `BY-DESIGN: property-disclaimed`.
+- `Channel.Init()` data race: `BY-DESIGN`, because documentation says it is 
not thread-safe.
+
+---
+
+## §14 Open questions for the maintainers
+
+Each question includes the draft recommendation and awaits PMC confirmation, 
correction, or deletion. After confirmation, the corresponding *(inferred)* 
tags in the body should be updated to *(maintainer)*.
+
+---
+
+### Wave 1 — scope, adversary, and the insecure-default rulings (must answer 
first)
+
+**Q1.** Is the server-side wire peer untrusted by default, so the runtime 
cannot assume input matches any registered protocol? Yes.  
+**Q2.** Is client-side deserialization of server responses in the same model 
scope as server-side handling of client requests? Yes.  
+**Q40.** Is `-max_body_size=64 MiB` a supported production default, or a 
baseline that operators must lower per deployment? Production default.  
+**Q50.** `has_builtin_services=true` + `internal_port=-1` puts built-ins on 
the main port by default; how should public exposure of `/flags`/`/version` be 
triaged? Operator responsibility.  
+**Q46.** `-immutable_flags=false` allows reachable `/flags` to modify 
reloadable gflags; should the default be changed to true? No, operator 
responsibility.  
+**Q57.** Client TLS does not verify server certificates by default; should 
successful MITM be `BY-DESIGN` or `VALID`/`VALID-HARDENING`? `BY-DESIGN`.  
+**Q56.** Is it acceptable that `ChannelSSLOptions.protocols` includes TLS 
1.0/1.1 by default? `BY-DESIGN`.  
+**Q51.** Is `force_ssl=false`, which makes a TLS port still accept plaintext, 
only operator responsibility? Operator responsibility.
+
+### Wave 2 — what the runtime does (and does not do) to its host
+
+**Q9.** Is bRPC explicitly an embedded library rather than a secure-by-default 
daemon? Yes.  
+**Q10.** Does the user handler run in the same process as the deserializer, 
with no sandbox provided by bRPC? Yes.  
+**Q11.** Are TLS/SSL cryptographic guarantees entirely inherited from OpenSSL? 
Yes.  
+**Q12.** Does bRPC validate only wire framing, not application field 
semantics? Yes.  
+**Q24.** Is Windows outside the security support environment? Yes.  
+**Q28.** Do maintainers agree that parser/read/decompress paths are 
memory-unsafe C++ attack surfaces? Yes.
+
+### Wave 3 — wire-protocol parser surface (per-protocol hardening parity)
+
+**Q8.** Is the list of default-on, opt-in, and client-only protocols accurate? 
Yes.  
+**Q37.** Should `enabled_protocols` ensure parsers not listed are never tried? 
Yes.  
+**Q22.** Should vulnerabilities in opt-in parsers be triaged as `OUT-OF-MODEL: 
non-default-build` when not enabled? Parsers are all enabled by default, so 
triage as `VALID`.  
+**Q80.** Do all parsers with length framing uniformly check 
`FLAGS_max_body_size`? Yes.  
+**Q59.** Does h2/HPACK have defenses against bomb, CONTINUATION flood, PING 
flood, and SETTINGS flood? Preferably yes.  
+**Q68.** Does `mcpack2pb` have recursion/depth caps? Preferably yes.  
+**Q69.** Does `json2pb` have a JSON depth cap? Preferably yes.
+
+### Wave 4 — built-in admin services trust model
+
+**Q4.** Is the trust status of built-in admin consumers determined entirely by 
operator exposure? Yes.  
+**Q19.** Should public access to default built-ins such as `/version` be 
triaged as operator responsibility? Yes.  
+**Q45.** Because `/dir` and `/threads` are disabled by default, should issues 
after public enablement be triaged as non-default-build? Yes.  
+**Q71.** Do profiler endpoint `seconds` parameters have reasonable upper 
bounds? How should DoS after exposure be triaged? Preferably yes.  
+**Q87.** Is there no isolation between built-in services, so a bug in one 
handler can affect other services in the same process? This is an issue.
+
+### Wave 5 — TLS / SSL / authentication
+
+**Q52.** Is `strict_sni=false` fallback to the default certificate a supported 
posture? Yes.  
+**Q54.** Is server-side mTLS being disabled by default a supported posture? 
Yes.  
+**Q90.** Which protocols does `Authenticator` actually cover? Does it not 
cover Thrift/Redis/memcache/Mongo/RTMP/nshead by default? Yes.  
+**Q77.** Is an authenticated peer still an untrusted adversary at the parser 
layer? Yes.  
+**Q47.** Does `-http_header_of_user_ip` have no built-in trusted-proxy 
verification? Yes; this is not an issue.
+
+### Wave 6 — resource bounds, compression, streaming
+
+**Q42.** Should streaming unconsumed bytes being unlimited by default change 
default behavior or require explicit operator configuration? Yes.  
+**Q70.** Is it confirmed that bRPC has no decompressed-output size cap? Should 
`-max_decompressed_size` be added? Preferably yes.  
+**Q73.** Is it true that there is no per-protocol/per-method body cap and only 
global `-max_body_size`? There is indeed none, and this is acceptable.  
+**Q74.** Is there no framework-level connection-count cap? None.  
+**Q82.** Can the resource policy be stated as: superlinear memory growth over 
the wire-declared size is a bug when constrained by `-max_body_size`? Yes.  
+**Q93.** Has the HTTP parser been audited for request smuggling defenses? Yes.
+
+### Wave 7 — concurrency, properties, and remaining open items
+
+**Q5.** Does RDMA require explicit build-time and runtime enablement, with 
related vulnerabilities out of model when not enabled? Yes.  
+**Q7.** Are `test/`, `example/`, `tools/`, and `community/` out of model? Yes. 
 
+**Q18.** Do wire bytes remain untrusted until the user's `Service::Method` is 
called? Yes.  
+**Q20.** Is client response parsing modeled equivalently to server request 
parsing? Yes.  
+**Q23.** Can crashes on malformed naming-service replies be `VALID`, while 
malicious backend redirection is out of model? Yes.  
+**Q72.** Should consul/nacos and similar naming-service parsers defend against 
malformed input? Yes.  
+**Q79.** Does bRPC have continuous fuzzing/OSS-Fuzz; if not, does P1 mainly 
rely on code review and CI? No.  
+**Q83.** Under the per-connection bthread model, is synchronization of 
application shared state entirely the user's responsibility? Yes.  
+**Q84.** Is per-request authorization implemented by `Interceptor` or the 
handler, not `Authenticator`? Yes.  
+**Q88.** Should cross-protocol sniffer confusion be handled as a framework 
`VALID` issue? Yes.
+
+---
+
+## §15 Optional: machine-readable companion
+
+v1 does not generate a machine-readable sidecar. After the defaults and triage 
decisions in §14 wave 1 stabilize, generate a derived index for tooling: entry 
points and parameter trust levels, in-scope/out-of-scope components, 
security-relevant gflag defaults, §8 properties, §9 disclaimed properties, §11a 
non-findings, and §13 disposition labels. This document remains the normative 
specification.
+
+---
+
+## Appendix: SECURITY.md statement -> threat-model § back-map
+
+At drafting time, the repository had no `SECURITY.md`, and the Apache security 
project index provided only the generic `[email protected]` address, with no 
bRPC project-level security page.
+
+| Source | Statement | Threat-model section |
+| --- | --- | --- |
+| `security.apache.org/projects/` | no project-level security content | N/A |
+| future `SECURITY.md` | TBD by PMC | to be backfilled in a future version |
+
+Once the PMC publishes `SECURITY.md` or an official security policy, that 
artifact should become a higher-authority source. This document should then map 
back to or link to the official document.
+
+---
+
+*End of v1 draft.*
+


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to