]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DOC: internals: add a threat model definition
authorWilly Tarreau <w@1wt.eu>
Sun, 31 May 2026 18:28:08 +0000 (20:28 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 31 May 2026 18:28:08 +0000 (20:28 +0200)
Add doc/internals/threat-model.txt describing what does and does not
qualify as a security vulnerability in HAProxy so that reporters and
developers have a common understanding of the threat model, and make it
clear that anything non-critical should be handled in the open and
not hidden behind embargoes.

The document lists assets to protect, what constitutes an attack, what
are the mitigations in place, and the severity ordering of various
risks. This may in the long term also help developers make better
choices of default settings and option names, and may also justify
changing default settings over time when modern operating systems
bring new possibilities.

A section also lists some invariants and defaults in an attempt to
limit the risk of reporting theoretical issues that are technically
impossible to happen in the field.

This is an initial version meant to be refined as cases arise. It
was incrementally designed and cross-checked with the help of three
independent LLMs (Qwen, Gemini and Claude) until each correctly
classified a set of sample reports against it. In the current state
they do not raise any residual ambiguities anymore.

doc/internals/threat-model.txt [new file with mode: 0644]

diff --git a/doc/internals/threat-model.txt b/doc/internals/threat-model.txt
new file mode 100644 (file)
index 0000000..50cfb99
--- /dev/null
@@ -0,0 +1,233 @@
+HAProxy Threat Model & Trust Boundaries
+
+This document defines the security boundaries of HAProxy, explicitly outlining
+what does and does not constitute a security vulnerability. Its purpose is to
+give reporters, developers and reviewers a single, predictable basis for
+judging an issue's real-world impact.
+
+The project's strong preference is to fix issues quickly and in the open.
+Public handling gets fixes to users sooner and spares the ecosystem
+(distributions in particular) the heavy cost of embargo coordination, which in
+practice has rarely served users. Private, coordinated disclosure is reserved
+for the few cases whose real-world impact genuinely warrants it, judged from
+the severity ordering (section 6) and the mitigations (section 5). An issue
+that is technically in scope but contained in practice does not, by itself,
+call for an embargo.
+
+These boundaries apply strictly to officially supported, documented builds
+running under a sane, production-ready configuration. Security guarantees are
+explicitly voided when using opt-in unsafe knobs, undocumented behavior, or
+experimental features. A configuration that merely lacks a recommended
+hardening step (for instance, no chroot) does not by itself move a
+client-triggered bug out of scope; the missing mitigation only widens the
+blast radius (sections 5 and 6).
+
+1. ASSETS TO PROTECT
+   HAProxy sits on the critical path of the services it fronts, so its
+   availability and the integrity and confidentiality of the configuration and
+   secrets it holds are all essential to protect. The assets below are not
+   ranked here; their relative severity is ranked in section 6.
+   - Integrity and confidentiality of the host and configuration: a compromise
+     of the network-facing worker must not extend to the filesystem, nor to the
+     configuration and its dependencies (private keys, Lua scripts, maps,
+     crt-lists, ACLs). On a properly configured system the default structural
+     mitigations prevent this, leaving only a compromise of the master process
+     as a residual path (see section 5).
+   - Confidentiality of long-lived secrets: TLS private keys and certificates
+     above all. Unlike transient client data, their disclosure is permanent and
+     systemic (impersonation and traffic decryption until every key is rotated
+     and revoked).
+   - Availability of the proxied service: being on the critical path, keeping
+     HAProxy serving is paramount. A small, cheap amount of attacker input
+     must neither consume a disproportionate amount of CPU or memory
+     (asymmetric DoS, see section 3) nor crash or stall the process.
+   - Confidentiality and isolation of client data: data belonging to one
+     connection, stream or client must never leak to another, and process
+     memory (including uninitialized memory) must never leak to a client.
+   - Process integrity (memory safety): no RCE, memory corruption or undefined
+     behaviour (UB) reachable from untrusted input.
+   - Correct enforcement of the configured policy: access controls, routing and
+     header manipulations decided by the configuration must not be bypassable
+     by crafted input.
+
+2. ATTACKER AND ENTRY POINTS
+   - The reference attacker is an untrusted client able to send arbitrary
+     bytes to a frontend: raw TCP payloads, HTTP/1, HTTP/2 and HTTP/3 (QUIC)
+     traffic, and arbitrary TLS handshake records.
+   - Entry points in scope are therefore the listeners and everything that
+     parses or transforms client-supplied data: TLS, the HTTP muxes, HTX,
+     header/URL processing, sample fetches and converters acting on request
+     data, stick-tables fed by client data, the cache, and the QUIC/H3 stack.
+   - A secondary untrusted source is the DNS resolver path: even though
+     nameservers are configured, their answers arrive over UDP and can be
+     spoofed by an off-path attacker, so the response parser handles
+     attacker-influenced input.
+
+3. WHAT QUALIFIES AS A SECURITY BUG (IN SCOPE)
+   - Memory-safety issues (overflow, out-of-bounds, use-after-free, type
+     confusion, UB) reachable from untrusted client input.
+   - Cross-client or cross-stream effects: HTTP request smuggling, response
+     splitting, cache poisoning, and any mixing of data between concurrent
+     streams or connections (notably in the H2/H3 multiplexers).
+   - Disclosure of process memory or of another client's data to a client.
+   - Bypass of a policy that the configuration is meant to enforce (e.g.
+     defeating an http-request deny/acl through request crafting).
+   - Asymmetric / algorithmic denial of service: a single or a few cheap
+     requests causing disproportionate CPU or memory usage (hash-collision
+     flooding, catastrophic regex backtracking, quadratic parsing, unbounded
+     allocation, etc). This is distinct from volumetric DoS (see 4).
+   - Misuse of a third-party library on untrusted input: feeding malformed
+     client data into OpenSSL, PCRE, Lua, zlib, etc. in a way that corrupts
+     memory or crashes the process is in scope. A vulnerability inside the
+     library itself is handled by that library's project, not here.
+   - Mishandling of spoofable DNS responses: memory corruption, crashes or
+     cache/state poisoning in the resolver caused by a crafted DNS answer are
+     in scope, despite nameservers being nominally trusted (see section 2).
+
+4. WHAT DOES NOT QUALIFY (OUT OF SCOPE)
+   The following do not fall into the security-bug category.
+
+   Trusted peers, servers and protocols:
+   - attacks that require a non-compliant or malicious server: in a reverse
+     proxy, servers are trusted, or ejected. This covers server-to-client
+     attacks in general.
+   - attacks on protocols only used with trusted peers: peers, PROXY protocol,
+     CIP (NetScaler Client-IP insertion), SOCKS, a local server reached over
+     an ABNS or UNIX socket, an FCGI server, etc., as well as TLS servers
+     contacted by the internal httpclient.
+   - malfunction of a trusted auxiliary service (log server, ring output,
+     CLI API consumer, etc.).
+
+   Privileged or local access (the actor is already trusted):
+   - any problem triggered through admin access to the CLI.
+   - anything requiring access to the master CLI.
+   - anything requiring access to the command line.
+   - anything requiring write access to the configuration file or any of its
+     dependencies (Lua scripts, certificates, crt-list, acl, map, etc.).
+   - anything requiring a configuration running as root, or chrooted to "/"
+     (i.e. with no effective chroot).
+
+   Opt-in unsafe or experimental knobs (the operator disabled a safety):
+   - anything requiring "experimental-mode on" on the CLI.
+   - anything requiring "insecure-fork-wanted".
+   - anything requiring "accept-unsafe-violations-*".
+   - anything requiring "expose-experimental-directives".
+
+   Misconfiguration:
+   - anything requiring a configuration that emits warnings at boot.
+   - anything requiring a nonsensical configuration, e.g. a server looping back
+     to the frontend, non-standard header processing or URL rewriting, or an
+     excessively large number of headers or excessively large header/body
+     sizes.
+
+   Volumetric or otherwise detectable activity:
+   - anything requiring such a high and sustained level of activity that it
+     would be detected and blocked in production (e.g. billions of requests or
+     connections). This is volumetric DoS, as opposed to the asymmetric DoS of
+     section 3.
+
+   Inherent protocol limitations:
+   - anything that is a limitation of a standard protocol rather than an
+     implementation flaw. For example, HTTP/1 has no way to abort a single
+     transfer without closing the connection, so a client aborting a transfer
+     will necessarily cause the corresponding server-side connection to be
+     closed; this is by design of the protocol, not a vulnerability.
+
+   Features that are not security boundaries:
+   - the stats page, including its admin mode, relies on HTTP basic
+     authentication and was never meant to be a security boundary. Exposing a
+     public-facing, admin-enabled stats page is therefore not covered.
+   - configuring a listener to accept the PROXY protocol or CIP from senders
+     that are not restricted to trusted ones is a misconfiguration: these
+     headers are believed on trust, so the listener must be reachable only by
+     the trusted L4/L7 component that prepends them.
+
+   Side channels:
+   - cryptographic and micro-architectural side channels (timing, cache,
+     speculative execution, etc.) are out of scope. Constant-time handling of
+     secrets is pursued on a best-effort basis as ordinary hardening where it
+     clearly matters, but observable timing or resource variations are not
+     handled as security bugs.
+
+   Log integrity:
+   - escaping of data emitted to logs is a configuration responsibility.
+     Injection of control characters or forged fields through logged client
+     data (e.g. when default escaping is disabled, or when a downstream log
+     consumer mis-parses) is not covered.
+
+5. DEFENSE IN DEPTH (DEFAULT HARDENING)
+   A correctly deployed HAProxy combines several built-in mitigations that
+   bound the impact of a successful compromise. These are deliberately taken
+   into account when assessing the real-world severity of an issue and the
+   handling it deserves: when one of them contains the practical impact of a
+   bug, that bug rarely warrants a coordinated embargo and is usually better
+   fixed quickly and in the open, where users get the fix sooner. They lower
+   severity, not the obligation to fix: an exploitable memory-safety bug
+   reachable from client input is still corrected as a bug.
+   - No fork()/exec() in the worker: the worker never forks nor runs external
+     programs, so an attacker who achieves code execution has little ability
+     to spawn a shell or launch persistent background code. ("insecure-fork-
+     wanted" deliberately disables this and is itself out of scope, see
+     section 4.)
+   - chroot and privilege drop: in the sane configuration this document
+     assumes, the worker drops to an unprivileged user/group and chroots into
+     an empty, unwritable directory. Injected code therefore has no filesystem
+     access and very limited means to act on the host.
+   - Activity watchdog: a thread that stops making progress, e.g. hijacked
+     into an attacker-controlled loop or otherwise stuck, no longer services
+     the event loop; the watchdog detects this lack of activity and kills the
+     process after a few seconds rather than letting it be silently held.
+   - Master/worker separation: only the worker is exposed to the network and
+     runs the parsers reachable by clients, and it is the unprivileged,
+     chrooted process. The master keeps privileges and filesystem access but
+     has no network exposure. The master must therefore be protected as the
+     trusted, more privileged component; an attacker is assumed to face only
+     the worker. The master must under no circumstances be reachable from the
+     worker (e.g. a master CLI bound to a TCP socket such as localhost is
+     trivially reachable from compromised worker code and defeats this critical
+     separation).
+
+6. SEVERITY ORDERING
+   The worst-case outcomes below are ranked by their realistic impact on a
+   standard configuration, from most to least severe, and the effort spent
+   guarding against each is proportional to that severity. The ranking reflects
+   the master/worker privilege split and the containment provided by the
+   section-5 mitigations.
+     1. Remote code execution in the master process. The master is privileged
+        and has filesystem access, so compromising it defeats every
+        containment, leaks every secret, and can subvert or take down the
+        whole service.
+     2. Chosen disclosure of long-lived secrets, TLS private keys and
+        certificates above all. Unlike an outage the damage is permanent and
+        silent: stolen keys allow impersonation, interception and, absent
+        forward secrecy, decryption of captured traffic, until every affected
+        key is rotated and revoked across the ecosystem; a restart does not
+        undo it. "Chosen" sets this rank, not scope: any disclosure of process
+        memory or of another client's data to a client is in scope (section 3);
+        this top rank is reserved for a targeted exfiltration, where the
+        attacker steers the read to a known secret. A leak that cannot be
+        steered toward a specific secret is still an in-scope disclosure bug,
+        but ranks far lower - often no worse than the crash such a read tends
+        to cause first.
+     3. Crash of the master process. It brings the entire service down and
+        prevents workers from being respawned: a full but recoverable outage.
+     4. Crash of the worker process. A transient outage: in-flight connections
+        are lost and traffic is interrupted for the fraction of a second it
+        takes to respawn.
+     5. Remote code execution in the worker process. Contained by no-fork,
+        chroot, privilege drop and the watchdog, its availability impact is
+        usually below a worker crash, except in the unlikely case where it
+        unlocks the chosen disclosure of level 2, which is hard to reach
+        through the internals from injected code.
+     6. Policy bypass. Serious, but with no direct availability impact.
+
+7. SECURITY-RELEVANT INVARIANTS AND DEFAULTS
+   The values below define the conditions HAProxy is designed to operate
+   within, and may be relied upon by parsing and processing code. A suspected
+   vulnerability that can only be triggered by conditions outside them
+   (typically values pushed beyond the stated limits) does not qualify as
+   security-relevant:
+   - trash buffers and struct buffer storage are always at least a few kB.
+   - default buffer size is 16 kB (15 kB max input, as 1 kB is reserved for
+     rewrites), tunable up to <256 MB.
+   - default log line is 1 kB, tunable up to <=64 kB.