Skip to content

Instantly share code, notes, and snippets.

@ppkarwasz
Created May 13, 2026 19:41
Show Gist options
  • Select an option

  • Save ppkarwasz/31da3ded5ca4d6b03db335126a27c6fd to your computer and use it in GitHub Desktop.

Select an option

Save ppkarwasz/31da3ded5ca4d6b03db335126a27c6fd to your computer and use it in GitHub Desktop.
Draft of Apache HTTP Server Threat Model

Apache HTTP Server 2.4.x — Threat Model

1. Header

  • Project: Apache HTTP Server (apache/httpd), branch 2.4.x
  • Repository commit basis: shallow clone of origin/2.4.x taken 2026-05-13
  • Date: 2026-05-13
  • Author: drafted by an external reviewer working from public artifacts; not yet ratified by the httpd PMC
  • Version binding: this document describes the implicit contract for the 2.4.x line as a whole. The release-stability policy in VERSIONING forbids breaking module API or runtime configuration within 2.4.x, so the threat model is expected to remain stable across patch releases. A report against a specific 2.4.<n> release should be triaged against this document as it stood at that tag.
  • Reporting cross-reference: vulnerabilities should be reported to security@httpd.apache.org per httpd.apache.org/security_report.html. Findings that fall under §3 or §9 of this document will be closed by reference to it.
  • Status: DRAFT v1, awaiting maintainer review. Many entries are (inferred) from public docs and source structure; all such entries route to §14.
  • Provenance legend: (documented) = stated in project's own docs or website; (maintainer) = stated by an httpd PMC member in response to this process; (inferred) = reasoned from source structure or docs absence, not yet confirmed.
  • Draft confidence: approximately 38 (documented) / 0 (maintainer) / 55 (inferred). The model is heavily inferred and should not be treated as authoritative until a maintainer wave has been processed.

Apache HTTP Server 2.4 is a long-running, mature, in-process-modular HTTP/1.1 and HTTP/2 origin and reverse-proxy server. It runs as a privilege-separated daemon (started as root, child workers run as a configured unprivileged user) on Unix-like systems and as a service on Windows, with additional platform support for OS/2 and NetWare. Functionality is delivered by loadable modules built against a stable C ABI; cryptography is provided by mod_ssl linked against OpenSSL, HTTP/2 by mod_http2 linked against libnghttp2, and the portability/utility layer by the bundled (but separately maintained) APR and APR-Util projects. Pluggable Multi-Processing Modules (MPMs — event, worker, prefork, plus platform-specific variants) define the concurrency model.

2. Scope and intended use

Primary intended uses (documented, README + ABOUT_APACHE):

  • Origin web server for static and dynamic HTTP/HTTPS content.
  • Reverse proxy / load balancer in front of application servers (via mod_proxy_*).
  • Reference implementation of the HTTP protocol.

Deployment context (inferred): a long-running daemon listening on one or more sockets, started by an operator with root (or equivalent) privileges and switching to an unprivileged user before handling requests. Not designed as a sandboxed in-process library, not designed for ephemeral / single-request invocation, not designed to host arbitrary user content without operator-imposed scoping.

Caller roles (inferred — there is no single "caller"):

Role Trust level Notes
HTTP client (browser, bot, attacker) untrusted Primary in-scope adversary.
Operator / sysadmin running httpd trusted Writes httpd.conf, selects modules, owns the host.
Module author (loaded via LoadModule) trusted A loaded module runs in-process with full server privilege — see §9.
Authenticated end-user (via mod_auth*) semi-trusted Identity is asserted, but the request body is still untrusted.
Backend origin (for mod_proxy_*) semi-trusted Operator chose the backend, but its responses are arbitrary bytes.
Tenant on shared hosting partial coverage suEXEC, UserDir, per-Directory permissions partially model this — but see §9 and §11.

Component-family table (documented for in/out flag, inferred for trust-profile commentary):

Family Path Description Touches outside process? In threat model?
Server core server/, include/*.h Config parser, request lifecycle, hook/filter dispatch, MPM bootstrap, util_expr, util_pcre, scoreboard net, fs, signals, env, sub-procs yes
MPMs server/mpm/{event,worker,prefork,winnt,mpmt_os2,netware} Concurrency models as core yes for event/worker/prefork/winnt; mpmt_os2/netware see §3
Bundled protocol modules modules/http/, modules/http2/ HTTP/1.1, HTTP/2 (mod_http2 + mod_proxy_http2) net yes
Bundled crypto module modules/ssl/ mod_ssl (depends on OpenSSL) net, fs (keys/certs) yes for the integration; OpenSSL itself out of scope
Bundled AAA modules modules/aaa/ Basic/Digest/Form auth, file/DBM/LDAP/socache backends fs, net (LDAP), DBM yes
Bundled cache / shared-cache modules/cache/ (mod_cache, mod_cache_disk, mod_cache_socache, mod_socache_*) HTTP cache, shared object cache backends (shmcb, DBM, memcache, redis, dc) fs, net, shm yes
Bundled proxy modules modules/proxy/ mod_proxy and submodules: http, ajp, fcgi, scgi, uwsgi, balancer, connect, express, fdpass, ftp, hcheck, html, wstunnel, http2 net (outbound) yes
Bundled generators modules/generators/ mod_cgi, mod_cgid, mod_autoindex, mod_status, mod_info, mod_suexec (wrapper), mod_asis sub-procs (CGI), reveal-internal (info/status) yes
Bundled filters modules/filters/ mod_deflate, mod_brotli, mod_include (SSI), mod_sed, mod_substitute, mod_ratelimit, mod_reqtimeout, mod_proxy_html, mod_xml2enc, mod_buffer, mod_ext_filter, mod_request, mod_data, mod_reflector, mod_charset_lite depends on filter yes
Bundled mappers modules/mappers/ mod_alias, mod_rewrite, mod_dir, mod_userdir, mod_negotiation, mod_speling, mod_actions, mod_imagemap, mod_vhost_alias fs yes
Bundled metadata modules/metadata/ mod_headers, mod_env, mod_setenvif, mod_remoteip, mod_expires, mod_unique_id, mod_mime_magic, mod_ident, mod_usertrack, mod_version, mod_cern_meta depends yes
Bundled DAV modules/dav/main/, modules/dav/fs/, modules/dav/lock/ WebDAV core, filesystem provider, lock manager fs yes
Bundled scripting modules/lua/ (mod_lua) Embedded Lua VM runs scripts as server user yes
Bundled session modules/session/ session, session_cookie, session_crypto (depends on apr_crypto), session_dbd fs/db, crypto via apr_crypto yes
Bundled logging modules/loggers/ mod_log_config, mod_log_forensic, mod_log_debug, mod_logio fs, pipe-to-logger yes
Bundled ACME / cert mgmt modules/md/ mod_md (Let's Encrypt / ACME), depends on libcurl + OpenSSL JWS net (outbound), fs (key/store) yes
Bundled LDAP util modules/ldap/ (util_ldap) LDAP cache/utility used by mod_authnz_ldap and others net (LDAP) yes
Bundled cluster modules/cluster/ mod_heartbeat, mod_heartmonitor (multicast cluster signalling) net (multicast) yes (inferred — confirm)
Bundled database framework modules/database/ (mod_dbd) SQL connection pooling for modules net (DB) yes
Bundled slotmem modules/slotmem/ (plain, shm) Shared-memory slot allocator used by mpm/event, mod_proxy_balancer, etc. shm yes
Support binaries support/ (htpasswd, htdbm, htdigest, htcacheclean, rotatelogs, logresolve, fcgistarter, ab, suexec) Separately invoked utilities; suexec is a setuid-root helper fs, sub-procs, net (ab) yes for suexec; see §3 for the rest
Experimental modules modules/experimental/ "not supported officially" per modules/README (documented) varies no — §3
Test modules modules/test/ "You should not compile these into a production server" per modules/test/README-historical and modules/README (documented) varies no — §3
Example modules modules/examples/ "sample code that should help you on your way to develop your own Apache modules" per modules/README (documented) varies no — §3
mod_echo modules/echo/ TCP echo example net no — §3 (inferred — confirm)
Bundled libraries srclib/apr, srclib/apr-util, srclib/pcre APR, APR-Util, PCRE — separately released projects vendored for convenience n/a no — §3; treated as upstream dependencies

3. Out of scope (explicit non-goals)

Code in the tree that is not modelled here:

  • modules/experimental/(documented, modules/README): "we've placed some modules which we think provide some pretty interesting functionality, but which are still in the early stages of development and could evolve radically in the future. This code isn't supported officially." A finding here is OUT-OF-MODEL: unsupported-component.
  • modules/test/(documented, modules/README): "You should not compile these into a production server." Includes mod_dialup and the optional-fn/hook export/import test pairs. (inferred) — confirm whether mod_dialup is genuinely test-only or has any deployed users.
  • modules/examples/(documented, modules/README and modules/examples/README): scaffolding for third-party module authors. mod_example_hooks is functional but exists to demonstrate the API.
  • modules/echo/(inferred): a small TCP-echo example, structurally similar to examples/. No README claims production support. Open question 14-Q1.
  • srclib/apr, srclib/apr-util, srclib/pcre — separately released and maintained projects, vendored by some distributions. A finding in APR is reported to APR, not httpd; this document does not extend httpd's claims to them.
  • Third-party modules (anything in mod_* packaged outside this repository) — out of scope. The operator's choice to load a third-party module is itself an operator-trust decision (see §10).
  • The support binaries other than suexechtpasswd, htdbm, htdigest, ab, htcacheclean, rotatelogs, logresolve, fcgistarter — are admin-side CLI tools. They process operator-controlled inputs in operator-controlled contexts. A finding that requires the operator to feed attacker-controlled input into one of these utilities is typically OUT-OF-MODEL: trusted-input unless the utility is documented as accepting untrusted input. Open question 14-Q2 — confirm scope per utility, especially ab (typically used as a benchmarking client of a system under test, not a server-side component).
  • Configuration files (httpd.conf, included files, .htaccess when AllowOverride permits) — the contents of these files are an operator artifact, not an input from the threat model's adversary. A finding that requires "if the operator writes Foo bar then X happens" is OUT-OF-MODEL: trusted-input unless the directive's documented contract is itself violated. (.htaccess files contain operator-delegated configuration; see §11 for the misuse pattern of delegating to untrusted authors.)
  • Build process, release signing, CI configuration, dependency hygiene — out of scope per SKILL.md §1.

Threats explicitly not defended against:

  • Generic denial-of-service at network or OS layer(documented, security_report.html): "all networked servers are subject to denial of service attacks, and we cannot promise magic workarounds to generic problems (such as a client streaming lots of data to your server, or re-requesting the same URL repeatedly)." See §8 for the (documented) converse: non-linear resource consumption is in scope.
  • Distributed denial-of-service (DDoS)(documented, docs/manual/misc/security_tips.html): "Often the most effective anti-DoS tool will be a firewall or other operating-system configurations. […] Of course this is no help against Distributed Denial of Service attacks (DDoS)." Mitigation is operator/network-layer responsibility.
  • An operator who misconfigures the server — operator misconfiguration is not a vulnerability in httpd code; it is OUT-OF-MODEL: trusted-input (the operator is the trusted caller of the configuration API).
  • A loaded module that misbehaves — modules execute with the same privilege as the server core and can violate any §8 property at will. LoadModule is an operator-trust action, not a sandbox.
  • A malicious CGI script / dynamic content backend(documented, security_tips.html): "you must trust the writers of the CGI scripts/programs… CGI scripts can run essentially arbitrary commands on your system with the permissions of the web server user." This is operator/content-author responsibility, not httpd's.
  • Co-tenant attacks on shared hosting beyond what suEXEC and per-Directory permissions explicitly model(documented, suexec.html): suEXEC is opt-in, requires careful operator configuration, and is explicitly not a sandbox.
  • Side-channel attacks (inferred) — timing, cache, microarchitectural side channels are not in the published model. Open question 14-Q3.
  • TLS/crypto algorithm choice and key managementmod_ssl provides directives for cipher/protocol selection but the policy choice (and key handling outside httpd) is the operator's. Underlying cryptographic primitive flaws are OpenSSL's threat model, not httpd's.

4. Trust boundaries and data flow

The boundary between untrusted (an HTTP client over the network) and trusted (everything inside the running httpd process, plus the configuration files, plus the local filesystem, plus loaded modules, plus backend origins for proxy mode) lives at the listening socket.

A request enters the server as a stream of bytes on a TCP connection (optionally inside a TLS session terminated by mod_ssl). It is parsed by the active protocol module (mod_http for HTTP/1.1, mod_http2 for HTTP/2), turned into a request_rec, walked through the configured hook chain (translate_name → map_to_storage → access_checker → check_user_id → auth_checker → type_checker → fixups → handler), and either dispatched to a handler or proxied to a backend. Response bytes traverse the filter chain and return on the same connection.

Trust transitions (inferred):

  1. Bytes on socket → parsed request_rec: every input field becomes attacker-controlled at this point. Length and format limits (LimitRequestLine, LimitRequestFields, LimitRequestFieldSize, LimitRequestBody, LimitXMLRequestBody) are enforced here; values exceeding the limit are rejected. (documented in security_tips.html)
  2. request_rec → translated path: mod_alias / mod_rewrite / mod_userdir / mod_vhost_alias may transform URI into filesystem path. After this transition the path is "post-policy" — i.e., the operator's translation rules have applied — but it is still derived from attacker bytes.
  3. Translated path → filesystem access: mod_authz_host / mod_authz_core / per-Directory configuration must have granted access before any read. The Require all denied default (when configured per security_tips.html) blocks anything not explicitly allowed.
  4. mod_proxy_* outbound: the server becomes a client to a backend. Backend response bytes re-enter the request lifecycle as the response body and traverse the response filter chain. Open question 14-Q4 — is the backend treated as semi-trusted (typical of operator-chosen origins) or as fully untrusted (typical of ProxyPass-to-arbitrary-upstream)?

Reachability preconditions per family (the question a triager applies before any further analysis):

Family Reachable iff
Server core (request lifecycle) request bytes arrive on a listening socket.
mod_http / mod_http2 the connection has negotiated the corresponding protocol; HTTP/2 additionally requires the operator's Protocols directive to include h2/h2c.
mod_ssl a TLS-enabled Listener with SSLEngine on.
mod_proxy_* (forward/reverse) operator has configured ProxyPass, ProxyRequests, ProxyPassMatch, etc.; forward proxy requires explicit ProxyRequests On (documented, mod_proxy).
mod_cgi / mod_cgid a CGI handler is configured (ScriptAlias, AddHandler cgi-script, or Options +ExecCGI).
mod_lua a Lua handler/hook is configured.
mod_dav Dav On is set on a location, and mod_dav_fs (or another provider) is loaded.
mod_status / mod_info a handler is mapped to a location; a finding that requires mod_status reachable without Require restriction is in-model only if the documented hardening (restrict to admin IPs) is not required for safety — see §11.
mod_rewrite RewriteEngine On plus rules.
AAA modules a Require line referencing the provider, plus the provider's data source (file/DBM/LDAP).
Filters (mod_deflate, mod_brotli, mod_include, mod_sed, mod_substitute, …) the filter is inserted into the input or output chain by configuration.
mod_md MDomain directive configured.
suexec the helper binary is installed setuid-root, configured at build time, and mod_suexec is loaded with a SuexecUserGroup directive on a CGI request.

A finding against a module's code that requires a configuration the operator would not realistically have is OUT-OF-MODEL: trusted-input (the configuration is the trusted input). A finding that manifests only under the default-shipped configuration is in scope.

5. Assumptions about the environment

  • Operating system (documented, README.platforms): Unix-like (Linux, BSDs, Solaris, AIX, macOS) and Windows are tier-1. OS/2 and NetWare have dedicated MPMs and platform code but Open question 14-Q5 — confirm current support tier for OS/2 and NetWare in 2.4.x; absence of recent commits in those trees suggests they may be "compiles but unsupported for security purposes."
  • Concurrency (inferred): the server is intentionally multi-process and/or multi-threaded. With prefork MPM the request handler runs in a single-threaded child; with worker and event MPMs each child is multi-threaded and modules must be thread-safe. The model assumes the platform's pthreads/Windows threading is correct and that the configured MPM matches the modules in use (e.g., mod_php traditionally requires prefork).
  • Memory model and integer width (inferred): APR abstracts most platform details; the project assumes a conformant C99 toolchain and that size_t does not wrap on the supported architectures for any input that has already passed the LimitRequest* checks. Open question 14-Q6 — confirm whether 32-bit builds remain in the supported set.
  • Filesystem (inferred): filesystem operations are mediated by APR; the model assumes path semantics consistent with POSIX or Win32 (canonicalisation behaviour, symlink semantics under FollowSymLinks / SymLinksIfOwnerMatch). A filesystem that returns lying stat results, races between stat and open, or supports unusual case folding may invalidate per-Directory permissions. The TOCTOU surface around SymLinksIfOwnerMatch is documented in the manual and is the operator's risk to accept.
  • Time / clock (inferred): mod_session, mod_auth_digest (nonces), mod_md (ACME order timing) and mod_ssl (certificate validity, OCSP stapling) assume a monotonic-or-near-monotonic system clock. Large clock jumps may produce auth/session/cert-validity weirdness but are not modelled as adversarial. Open question 14-Q7.
  • Network (inferred): the listening socket is reachable from arbitrary IPs; source-IP information from the kernel is trusted unless an operator has explicitly configured mod_remoteip to honour a forwarded header (in which case mod_remoteip's own trust policy applies).
  • Linked libraries (documented, README + module READMEs): APR + APR-Util provide the portability/utility layer; OpenSSL provides TLS for mod_ssl; libnghttp2 provides framing for mod_http2; PCRE provides regex (vendored); libcurl + JWS via OpenSSL for mod_md; libxml2 for mod_proxy_html / mod_xml2enc; zlib for mod_deflate; libbrotli for mod_brotli; Lua / LuaJIT for mod_lua. The threat model treats these as upstream dependencies with their own threat models. A vulnerability that is purely in OpenSSL is reported to OpenSSL.

What httpd's environmental footprint includes (i.e., side effects on the host) (inferred — confirm):

  • Opens TCP/UDP listening sockets per the operator's Listen directives. Open question 14-Q8.
  • Forks/spawns child processes (worker children per MPM, plus CGI child processes when mod_cgi/mod_cgid is in use, plus mod_md calling out to curl).
  • Writes to log files (ErrorLog, CustomLog, optional piped log programs) and, depending on configuration, to a PidFile, scoreboard files, mutex files, cache directories, and DAV lock databases.
  • Installs signal handlers (SIGHUP for graceful restart, SIGUSR1 for graceful stop, SIGTERM, SIGCHLD, etc.).
  • Reads environment variables; passes a sanitised subset to CGI children (PassEnv / SetEnv).
  • Drops to an unprivileged user/group via User / Group directives (after binding listeners).
  • Allocates large amounts of memory and disk in proportion to the configured MaxRequestWorkers, cache size, slotmem entries, and DAV state.

5a. Build-time and configuration variants

The supported httpd is a family of binaries: the security envelope is determined by which modules are compiled in, which are loaded at runtime, which MPM is selected, and the values of dozens of directives. The following are the variants the model has an opinion about:

Variant / Knob Default Effect on the model Maintainer stance
Loaded modules (LoadModule lines) Distribution-dependent. The upstream source ships modules but distributions choose which to enable. Each loaded module adds its own request-lifecycle hooks; an unloaded module is unreachable. (inferred) In-scope for any module shipped under modules/ except those listed in §3. 14-Q9.
MPM selection event is default on Unix in 2.4.x (inferred — confirm 14-Q10) prefork gives single-threaded children (eases use of non-thread-safe modules like mod_php in some builds); worker/event require thread-safe modules. (inferred — confirm 14-Q10)
--enable-mods-shared=... / static link varies Modules can be statically linked or built as .so. No security difference is claimed. (inferred)
--enable-http2 requires libnghttp2 Compiles mod_http2; runtime activation still requires Protocols h2[c]. (documented, modules/http2/README.h2)
--enable-ssl requires OpenSSL Compiles mod_ssl; runtime activation requires SSLEngine on and configured certificate/key. (inferred)
--enable-suexec + suEXEC build options off by default; opt-in suEXEC is explicitly not part of the default install. (documented, suexec.html) "it has been the decision of the Apache HTTP Server development team to NOT make suEXEC part of the default installation… To this end, suEXEC configuration requires of the administrator careful attention to details." (documented): opt-in; misconfiguration is operator responsibility; a report against suEXEC behaviour in a non-default build is in-model only if it would also be a finding under the explicitly-documented installation.
AllowOverride None (since 2.3.9) (documented, security_tips.html) Default-secure: .htaccess files are ignored. If the operator enables it, attacker-controlled .htaccess content (e.g., via writable web roots) becomes a configuration channel. (documented): the secure default is the supported posture. A finding that requires AllowOverride All plus attacker-writable content is OUT-OF-MODEL: trusted-input (inferred — confirm 14-Q11).
Require all denied at <Directory "/"> not the shipped default; documented as recommended Without it, anything reachable by URL is served. (documented, security_tips.html) "unless you take steps to change it, if the server can find its way to a file through normal URL mapping rules, it can serve it to clients." (documented): documented as a recommendation, not a hard requirement. The default ships permissive root access; a finding that requires the operator to "fix it" is insecure-default territory and 14-Q12 is the question that decides §13 disposition.
FollowSymLinks vs SymLinksIfOwnerMatch FollowSymLinks is the default on most distributions (inferred) SymLinksIfOwnerMatch adds a TOCTOU-vulnerable check per request; performance penalty acknowledged in docs. (inferred — confirm 14-Q13)
LimitRequest* directives non-zero defaults in core Caps on line length, header count, field size, body size, XML body size. (documented, security_tips.html) (documented) hardening lever.
RequestReadTimeout, TimeOut, KeepAliveTimeout non-zero defaults Mitigate slowloris-class attacks. (documented)
mod_status / mod_info enabled and unrestricted not default If enabled and reachable from the network, leaks operational state. (documented, see §11): hardening doc recommends restricting to localhost / admin IPs.
UserDir enabled for root default = disabled root is recommended but not the ship default (inferred — confirm 14-Q14) Without UserDir disabled root, requests to /~root/ traverse root's home. (documented, security_tips.html) recommendation.
ProxyRequests On (forward proxy) off by default Turning on without restricting <Proxy> is well-known to make httpd an open proxy. (documented in mod_proxy docs — confirm 14-Q15)
Options +Includes (SSI) and +IncludesNOEXEC not default SSI with exec cmd runs arbitrary commands as the server user. (documented, security_tips.html): "SSI files also pose the same risks that are associated with CGI scripts in general." (documented): operator opt-in.
MaxRequestWorkers, slotmem sizing varies by MPM Determines worst-case process/memory footprint under load. (documented) tuning lever.
Mutex directive backends platform-dependent default Choice between flock, fcntl, sysvsem, posixsem, pthread, sem affects portability and concurrency semantics. (inferred — confirm 14-Q16)

6. Assumptions about inputs

Network inputs (inferred trust labelling unless noted):

Surface Field / parameter Attacker-controllable? Caller / operator must enforce
Listening socket TCP connection, peer IP yes (IP is observed by the kernel; if mod_remoteip enabled, also the header) source-IP-based Require policies are only sound if forwarded-header trust is correctly configured
HTTP/1.1 request request line, headers, body yes LimitRequestLine, LimitRequestFields, LimitRequestFieldSize, LimitRequestBody; the request line is parsed before any auth
HTTP/2 request frame stream, HPACK-compressed headers, body, settings yes nghttp2 enforces protocol-level limits; H2* directives cap stream count, body size, etc.
TLS handshake ClientHello, SNI, ALPN, client cert (if mTLS) yes OpenSSL handles primitives; mod_ssl applies operator's SSLCipherSuite/SSLProtocol/SSLVerifyClient policy
Authentication credentials basic creds, digest response, form fields, cookies, mTLS cert yes matched against operator-provided users/passwords/cert chains
Backend response (mod_proxy) response headers, body, status, trailer semi-trusted (backend is operator-chosen, but its bytes are arbitrary) response filtering, header sanitisation by mod_proxy_html if HTML rewriting requested
LDAP server response (mod_authnz_ldap, util_ldap) LDAP search results semi-trusted LDAP server is operator-chosen
OCSP responder (mod_ssl, mod_md) OCSP responses semi-trusted signature checked by OpenSSL against issuer chain
ACME server (mod_md) ACME directory, orders, challenges, certificates semi-trusted (operator picks the CA) TLS + JWS signature checks
Memcached / Redis / DBM cache (mod_cache_socache, mod_socache_*) cached object bytes yes if the cache is shared with another writer; otherwise self-produced operator must not share a socache backend with untrusted writers

Filesystem inputs (inferred unless noted):

Surface Trust Notes
httpd.conf and Included files trusted (operator-authored) configuration is not an adversary-controlled input
.htaccess files inside DocumentRoot partially trusted trust depends on AllowOverride and on whether the directory is writable by non-operators (see §11)
Files served as static content trusted (operator-authored) at the file level; filename is attacker-controlled via URI path-translation logic must reject path traversal, decoded-slash tricks, etc.
CGI scripts fully trusted (documented, security_tips.html) a malicious CGI script is not an httpd issue
Lua scripts (mod_lua) fully trusted same as CGI
Cert/key files (mod_ssl, mod_md) trusted file permissions are operator's responsibility
Password / DBM / group files (mod_auth*) trusted created via htpasswd/htdbm/htdigest by the operator
WebDAV-uploaded content (mod_dav) untrusted, but mediated by authentication and per-Directory permissions bytes written via PUT are authenticated by mod_auth* but the content should be treated as user content

Configuration directives are not adversary input. Every * value the operator puts in a directive is trusted: directive parsers are required to reject syntactically invalid input cleanly, but they are not required to defend against operator-supplied malicious values.

7. Adversary model

Primary in-scope adversary: a remote HTTP client capable of:

  • Opening arbitrary numbers of TCP connections (subject to OS / firewall limits).
  • Speaking HTTP/1.0, HTTP/1.1, or HTTP/2 (when negotiated) in arbitrary, including malformed, ways.
  • Optionally establishing a TLS session (and within it, sending arbitrary HTTP).
  • Triggering arbitrary handler/module/filter combinations reachable under the operator's configuration.
  • For mTLS: presenting a certificate from a configured trust root.
  • For WebDAV: authenticating with valid credentials and writing arbitrary file content within the DAV-mediated scope.

The adversary is assumed to want (inferred): remote code execution, information disclosure (file contents, internal state via mod_status/mod_info, memory contents via OOB read), authentication bypass, request smuggling between fronted services, cache poisoning, server crash, non-linear resource exhaustion (CPU/memory/file descriptors disproportionate to attacker effort), HTTP response splitting, log injection.

Out of scope adversaries:

  • An attacker with local shell access on the host as the server user or root — they have already won and there is nothing this layer can defend against.
  • An attacker who can modify httpd.conf, included files, loaded modules, or the on-disk binaries — these are operator-trust artefacts. Compromise of the operator's configuration channel is outside the model. (documented, security_tips.html): file permissions on ServerRoot, the binary, and logs are explicitly the operator's responsibility.
  • A malicious operator — uninteresting; the operator is the trusted caller of the configuration API.
  • A malicious module author whose module the operator chose to loadLoadModule is a privilege-equivalent action; module misbehaviour is the module's threat model, not httpd's.
  • A malicious CGI script writer or dynamic-content backend author — explicitly disclaimed (documented, security_tips.html).
  • A co-tenant on shared hosting beyond what suEXEC, per-Directory permissions, and UserDir disabled model — operator chooses the isolation primitives and accepts their limits.
  • A side-channel adversary (inferred): timing, microarchitectural, cache, and acoustic side channels are not modelled. 14-Q3.
  • An attacker on the network path between server and backend (for mod_proxy) — if the operator runs the backend connection over plaintext, that's the operator's choice; SSLProxyEngine is the documented tool for the case where the path is untrusted.
  • An attacker who can replace OpenSSL, libnghttp2, or other linked libraries on disk — outside the model.

8. Security properties the project provides

Each property below names the symptom that would constitute a violation and the severity tier it would fall into. The severity definitions are (documented) verbatim from httpd.apache.org/security/impact_levels.html:

Critical — "could potentially be exploited by a remote attacker to get Apache to execute arbitrary code (either as the user the server is running as, or root). These are the sorts of vulnerabilities that could be exploited automatically by worms." Important — "could result in the compromise of data or availability of the server. […] this includes issues that allow an easy remote denial of service (something that is out of proportion to the attack or with a lasting consequence), access to arbitrary files outside of the document root, or access to files that should be otherwise prevented by limits or authentication." Moderate — "if there is significant mitigation to make the issue less of an impact […] flaw does not affect likely configurations, or it is a configuration that isn't widely used, or where a remote user must be authenticated in order to exploit the issue. Flaws that allow Apache to serve directory listings instead of index files are included here, as are flaws that might crash an Apache child process". Low — "issues that are believed to be extremely hard to exploit, or where an exploit gives minimal consequences."

Properties:

  1. Memory safety on protocol-conformant input within configured LimitRequest* bounds. Within LimitRequestLine/LimitRequestFields/LimitRequestFieldSize/LimitRequestBody/LimitXMLRequestBody, the parsing code in modules/http/ and modules/http2/ is expected to produce a valid request_rec or a clean 4xx response without OOB reads, OOB writes, or use-after-free. Violation symptom: crash of a child, OOB read/write reachable from a network request, memory disclosure. Severity: Critical if RCE; Important / Moderate otherwise. (inferred — confirm 14-Q17; the project clearly treats memory-safety issues as in-scope per CVE history shape, but explicit phrasing of this property as a claim is not in the docs we surveyed.)

  2. Non-linear resource consumption in input size is a vulnerability. (documented, security_report.html) — "In general our philosophy is to avoid any attacks which can cause the server to consume resources in a non-linear relationship to the size of inputs." This is the project's published DoS line. Threshold: super-linear CPU/memory in input size is a bug; linear-in-input-size resource use (a large body costs proportional time/memory) is not. Violation symptom: a client request whose CPU or memory cost grows super-linearly with bytes sent. Severity: Important if it allows easy remote DoS; Low / Moderate otherwise. (documented)

  3. Operator-defined access control is enforced as documented. Require, <Directory>, <Location>, <Files>, mod_authz_core policy, mod_ssl certificate-based auth, and the AAA module chain are expected to produce the result the operator wrote down. Violation symptom: a request matched by a deny rule produces a 2xx; an unauthenticated request reaches an authenticated location; a directory restricted to one CIDR is reached from another. Severity: Important (per ASF defn) for "access to files that should be otherwise prevented by limits or authentication"; Critical if it composes into RCE. (inferred — confirm 14-Q17.)

  4. Path-translation does not allow escape from the operator's configured roots. URL → filesystem mapping by mod_alias/mod_rewrite/mod_userdir/mod_vhost_alias plus per-Directory permissions are expected to keep served files within the operator's allowed scope, given a correct configuration. Violation symptom: path traversal, encoded slash bypass, alias rewriting that escapes a ScriptAlias boundary, file disclosure outside DocumentRoot. Severity: Critical (per ASF defn — explicitly listed: "access to arbitrary files outside of the document root"). (documented in impact_levels.html)

  5. HTTP request boundaries are unambiguous between httpd and any peer. Front-end / back-end / fronted-server cases (HTTP/1.1 chunking + Content-Length, HTTP/2 → HTTP/1.1 downgrade, proxy forwarding) must not produce a request-smuggling differential. Violation symptom: a request that two cooperating peers parse differently, allowing one user's request to ride on another's connection. Severity: Critical or Important depending on what is reachable. (inferred — confirm 14-Q17.)

  6. TLS, when configured, terminates at mod_ssl with confidentiality and integrity provided by the underlying OpenSSL library. (inferred) The property mod_ssl claims is correct use of OpenSSL — primitive correctness is OpenSSL's claim. Violation symptom: a client sees plaintext on the wire when SSL should be in use; an mTLS handshake accepts an unauthorised cert; a downgrade to a forbidden protocol/cipher is reachable. Severity: Important typically. (inferred — confirm 14-Q17.)

  7. HTTP/2 stream / frame protocol compliance. (inferred) The stream multiplexer enforces nghttp2's protocol limits, the operator's H2MaxSessionStreams, body limits, and connection-flow-control budget. Violation symptom: a single connection consuming unbounded CPU/memory by abusing protocol features (rapid stream open/close, HPACK bombs, oversized continuation frames, etc.). Severity: Important typically. (inferred — confirm 14-Q17.) HTTP/2 rapid-reset (CVE-2023-44487) is the canonical example of this class.

  8. Privilege separation: the long-lived workers run as the configured unprivileged user/group. (documented, security_tips.html — implicit in the entire ServerRoot-permissions discussion) The parent process retains root only as long as needed to bind privileged ports and read config; child processes that service requests run as User/Group. Violation symptom: a child process running as root, or as a user other than the configured one. Severity: Critical. (inferred — confirm 14-Q17.)

  9. Module ABI stability within 2.4.x. (documented, VERSIONING) Loaded modules do not need to be recompiled across patch releases; runtime configuration is forward-compatible. This is a stability claim, not strictly a security claim — but its violation invalidates the assumption that the operator's tested module set still works after a security update.

9. Security properties the project does not provide

State plainly:

  • No defence against generic, linear, large-volume DoS. (documented, security_report.html) "all networked servers are subject to denial of service attacks, and we cannot promise magic workarounds to generic problems (such as a client streaming lots of data to your server, or re-requesting the same URL repeatedly)." The defence belongs at the firewall, OS, or upstream load-balancer layer.
  • No defence against DDoS. (documented, security_tips.html) See §3.
  • No isolation between loaded modules. A loaded module runs with the full privilege of the server worker. There is no sandbox, no permission system, no per-module capability model. LoadModule is privilege-equivalent.
  • No defence against malicious modules or malicious CGI / dynamic-content backends. (documented, security_tips.html) "CGI scripts can run essentially arbitrary commands on your system with the permissions of the web server user".
  • No defence against an operator who writes an insecure configuration. Misconfiguration is OUT-OF-MODEL: trusted-input.
  • No defence against an attacker who can write to httpd.conf, the binary, the logs, or DocumentRoot files. (documented, security_tips.html): file permissions are the operator's responsibility.
  • No constant-time guarantees on credential comparison, MAC verification, or session-token comparison. (inferred) — the project has no published claim that secret-comparison code is constant-time. 14-Q18.
  • No cryptographic strength claim. Crypto primitives come from OpenSSL (mod_ssl, mod_session_crypto via apr_crypto, mod_md via OpenSSL JWS). Their threat models govern.
  • No replay protection for arbitrary authenticated requests. Replay protection at the message level is the application's concern; mod_auth_digest nonces protect digest auth specifically; mTLS protects the channel.
  • No CSRF protection. httpd does not generate or check CSRF tokens; that is application-layer.
  • No XSS, SQLi, or general "web app vulnerability" defence. httpd is a transport / hosting layer.
  • No rate limiting per IP / per user by default. mod_ratelimit shapes bandwidth; it is not a request-rate limiter. 14-Q19 — should mod_ratelimit be called out as a false friend?
  • No web application firewall. (documented, security_tips.html) recommends ModSecurity as a third-party WAF.
  • No defence against side-channel observation. (inferred — 14-Q3.)
  • No protection against an attacker who can compromise the trust roots used by SSLCACertificateFile or MDCertificateAuthority. Trust-anchor management is the operator's job.

False friends (features that look like they provide a security property but do not):

  • mod_status and mod_info are not access-restricted by themselves. They expose worker state, configuration, and module list to anyone who can reach them. The hardening doc directs operators to put them behind a Require rule. Reading "I see mod_status in the module list, therefore httpd exposes server state to anyone" is correct under default configuration. (documented, security_tips.html and module docs)
  • mod_remoteip does not authenticate the forwarded header. It replaces c->client_ip with a value taken from X-Forwarded-For (or operator-configured equivalent) for any connection from an IP listed in RemoteIPInternalProxy / RemoteIPTrustedProxy. If that list is overbroad, source-IP-based access control is bypassable. (documented, mod_remoteip doc — confirm 14-Q20.)
  • suEXEC is not a sandbox. (documented, suexec.html): "if suEXEC is improperly configured, it can cause any number of problems and possibly create new holes". It is a UID-switch wrapper with 20 sanity checks; it does not isolate filesystem, network, or kernel surface.
  • Options -FollowSymLinks / +SymLinksIfOwnerMatch is not a perfect anti-symlink-traversal defence. The latter has a documented TOCTOU window and a performance penalty.
  • AllowOverride None (the default) does not mean .htaccess files are ignored everywhere. It is the default at <Directory "/"> since 2.3.9; if the operator scopes AllowOverride to a subtree, that subtree honours .htaccess.
  • SSLProxyVerify defaults to none. Out of the box, when httpd proxies to an HTTPS backend, it does not validate the backend's certificate unless the operator turns this on. 14-Q21 — confirm the default and whether the model treats this as a §10 operator duty or as a §11 misuse pattern.
  • HTTP Connection: close is not a sufficient defence against HTTP-pipelining-based smuggling differentials when proxying.
  • Basic auth over plaintext HTTP is not authentication. Documented but worth restating.
  • A successful CGI exit code is not a proof of script safety. (documented, security_tips.html).

Well-known attack classes against this category of project, left to the caller / operator / dependency:

  • HTTP request smuggling between httpd and a fronting/back-end peer that parses CL/TE/HTTP/2-downgrade differently — bounded by §8.5 within httpd, but cross-peer differentials require the operator to align peer behaviours.
  • HTTP response splitting via untrusted bytes injected into Header/RequestHeader directives or response headers via mod_proxy.
  • Cache poisoning via header-keyed caching when an unkeyed header is reflected — operator's caching policy.
  • Open-redirect via untrusted target in mod_rewrite or mod_alias — operator's configuration.
  • Slowloris family — mitigated by mod_reqtimeout, RequestReadTimeout, KeepAliveTimeout (operator must tune).
  • HTTP/2 rapid-reset and stream-flood variants — the kind of issue that, when it produces super-linear resource use, is in §8.2.
  • TLS compression (CRIME) and HTTP compression oracle (BREACH) — application/operator level.
  • Symlink TOCTOU under SymLinksIfOwnerMatch — documented limitation.
  • mod_lua / SSI / CGI as RCE vectors when an attacker can write to a directory mapped to an executable handler — operator's job to prevent.
  • Server-side request forgery via mod_proxy if ProxyRequests On is enabled without restricting <Proxy>.

10. Downstream responsibilities

The operator must, at minimum:

  1. Apply security updates promptly. (documented, security_tips.html)
  2. Run the parent process as root only long enough to bind privileged ports; configure User and Group to an unprivileged account. (documented)
  3. Lock down filesystem permissions on ServerRoot, the httpd binary, configuration, and logs so that only root can write to anything httpd reads or executes. (documented)
  4. Add <Directory "/"> Require all denied </Directory> and explicitly grant access only to the directories that should be served. (documented)
  5. Add <FilesMatch "^\\.(?!well-known)"> Require all denied </FilesMatch> to keep dotfiles (.env, .git, etc.) from being served. (documented)
  6. Set UserDir disabled root (and ideally enumerate which system accounts may have UserDir). (documented)
  7. Set AllowOverride None outside of any subtree where .htaccess is genuinely needed, and never enable AllowOverride on a directory writable by non-operators. (documented)
  8. Tune RequestReadTimeout, TimeOut, KeepAliveTimeout on sites subject to DoS. (documented)
  9. Tune LimitRequestBody, LimitRequestFields, LimitRequestFieldSize, LimitRequestLine, LimitXMLRequestBody. (documented)
  10. Tune MaxRequestWorkers to bound the server's footprint. (documented)
  11. Pair an appropriate MPM with the module set in use (e.g., prefork for non-thread-safe modules such as mod_php in some builds). (documented in the MPM docs)
  12. Use a firewall to cap per-IP connection counts and to absorb DDoS. (documented)
  13. Restrict mod_status, mod_info, and any other diagnostic surface to administrative IPs. (documented)
  14. For shared hosting: install and configure suEXEC correctly if you intend CGI scripts to run as different per-user identities, and accept the explicit caveats in suexec.html. (documented)
  15. For reverse-proxying to TLS backends: enable SSLProxyVerify require and configure a CA bundle so that backend certificates are validated. 14-Q21.
  16. For mod_remoteip: only list trusted upstream proxies in RemoteIPInternalProxy/RemoteIPTrustedProxy, since downstream of those, source-IP-based access control depends on the forwarded header.
  17. For forward proxying: never set ProxyRequests On without locking down <Proxy> rules, lest httpd become an open proxy.
  18. For CGI / SSI / mod_lua: vet every script and treat scripts as code, not data. (documented)
  19. For SSI: prefer a distinct extension such as .shtml, not .html, and consider IncludesNOEXEC. (documented)
  20. Monitor ErrorLog, AccessLog, and mod_log_forensic regularly. (documented)
  21. For mod_ssl: choose SSLCipherSuite and SSLProtocol according to up-to-date guidance (the docs reference Mozilla's "modern compatibility" recommendations). (documented in README.h2 and mod_ssl docs)
  22. Do not modify suEXEC's compiled-in defaults without understanding the security implications. (documented, suexec.html)

11. Known misuse patterns

  • Exposing mod_status or mod_info to the internet — operational state, env, module list, configured handlers are returned to whoever asks.
  • Setting AllowOverride All on a directory the web tenant can write to — the tenant becomes able to load arbitrary handlers, override auth requirements, etc. via .htaccess.
  • Putting CGI scripts (or mod_lua scripts) in directories the operator does not personally control — every script is privileged code.
  • ProxyRequests On on a public-facing server — instant open proxy.
  • mod_remoteip with a too-broad RemoteIPInternalProxy list — header-based IP becomes spoofable from outside the intended trust boundary.
  • Trusting X-Forwarded-For (or any forwarded header) without mod_remoteip configured — putting the raw header into Require ip decisions, log fields, or rate-limit logic.
  • Reverse-proxying to an HTTPS backend without SSLProxyVerify require — backend identity is unverified.
  • Symbolic links from DocumentRoot to operator-sensitive paths combined with FollowSymLinks — equivalent to publishing those paths.
  • UserDir enabled for root — exposes root's home tree.
  • Mixing mod_php (which historically requires non-thread-safe builds) with a threaded MPM without checking — has produced real-world crashes.
  • Using SSI on .html / .htm extensions on shared hosting — every HTML file becomes parseable; exec cmd is reachable from any author.
  • Returning user-controlled bytes in response headers via Header set X $value where $value comes from a request — splitting / injection.
  • Caching responses whose Vary is incomplete — different-user content served from a single cache key.
  • Configuring <Location "/"> after <Directory "/"> with conflicting Require(documented misuse, security_tips.html): "even if <Directory "/"> denies access, a <Location "/"> directive might overturn it."
  • Logging requests to a file inside a directory httpd itself serves — log-poisoning becomes content disclosure.
  • Running htcacheclean against a cache directory that another httpd instance is actively writing to — race conditions; this is a documented operator-tool caveat.
  • mod_cgi plus mod_userdir plus untrusted users — any user can drop code that runs as the server user.
  • Long-lived mod_dav writeable scope on a server that also executes from that scope — DAV upload + handler-mapped extension = RCE.

11a. Known non-findings (recurring false positives)

The list is (inferred) on first draft; expansion expected when a maintainer wave runs. 14-Q22.

  • "strcpy/strcat/sprintf in module code" — the project has used these where lengths are bounded by prior LimitRequest* checks; per §8.1 the assumption holds within those limits. A finding must show a path that reaches the call with an unbounded length.
  • "Path traversal possible because URI contains .."request_rec URI normalisation (ap_unescape_url, ap_getparents, etc.) is applied before path translation. A finding must show a path that bypasses normalisation.
  • "Information disclosure via Server header"(documented, ASF Security) version disclosure on its own is not classed as security-relevant. ServerTokens Prod is an operator hardening lever, not a defect.
  • "Race condition in SymLinksIfOwnerMatch"(documented limitation): this is operator-accepted behaviour, not a bug.
  • "mod_status exposes server state" — by design when enabled and unrestricted; the operator is supposed to scope it. OUT-OF-MODEL: trusted-input (configuration).
  • "mod_info exposes module config" — same as mod_status.
  • "CGI script runs arbitrary code" — by design; that is what CGI is. §9 disclaims it.
  • "Loaded module reads memory of the server" — by design; loaded modules are in-process.
  • "Lua script has full filesystem access" — by design; mod_lua runs as the server user.
  • "htpasswd does not require a strong password" — it accepts what the operator types; the operator is the trusted caller.
  • "ab connects without certificate validation"ab is a benchmarking client invoked by an operator against a system under test; outside §13 scope per §3.
  • "Test code in modules/test/ is unsafe" — explicitly out of scope per modules/README.
  • "Unchecked input in modules/examples/" — explicitly out of scope.
  • "OpenSSL function returns unchecked" — only relevant when the resulting failure mode would violate a §8 property; primitive correctness is OpenSSL's claim.
  • "Configuration parser accepts a syntactically-strange directive value without rejecting it" — directives accept what the operator types; not a security finding unless it leads to a §8 violation.

12. Conditions that would change this model

Trigger a revision when:

  • A new protocol module ships in modules/ (e.g., HTTP/3 if it lands in 2.4.x via mod_http3). The new module gets its own row in the §2 table and per-input rows in §6.
  • The default value of an *Override, Options, Require, Limit*, Timeout*, H2*, Proxy*, SSL* directive changes.
  • A module is promoted from experimental/ to a supported family — its §3 entry moves into §2.
  • A module is removed or marked end-of-life.
  • The supported platform set changes (e.g., 32-bit support officially dropped, OS/2 / NetWare officially removed).
  • A dependency is replaced (e.g., a TLS backend other than OpenSSL becomes first-class).
  • A new attacker capability becomes common in practice — the rapid-reset class for HTTP/2 is a recent example.
  • A vulnerability report cannot be cleanly routed to any §13 disposition. The correct response is to revise the model (add to §8, §9, §11, or §11a), not to make an ad-hoc call on the report.

13. Triage dispositions

Disposition Meaning Licensed by
VALID Violates a §8 property via an in-scope adversary and in-scope input. §8, §6, §7
VALID-HARDENING No §8 property is strictly violated, but the API/default makes a §11 misuse easy enough that the project elects to harden it. Typically no CVE; fixed at maintainer discretion. §11
OUT-OF-MODEL: trusted-input Requires attacker control of an input the model marks trusted — configuration directive, loaded module, CGI script, on-disk file. §6, §3
OUT-OF-MODEL: adversary-not-in-scope Requires a capability the model excludes — local user, side-channel observer, cooperating module, attacker on the in-process side. §7
OUT-OF-MODEL: unsupported-component Lands in modules/experimental/, modules/test/, modules/examples/, modules/echo/, or in srclib/* (re-report upstream). §3
OUT-OF-MODEL: non-default-build Only manifests under a discouraged or opt-in §5a flag (suEXEC misconfiguration in a non-default build, --enable-... of an experimental, etc.). §5a
BY-DESIGN: property-disclaimed Concerns a property listed in §9 as not provided — generic DoS, side channels, in-process module isolation, CSRF, etc. §9
KNOWN-NON-FINDING Matches a documented recurring false positive in §11a. §11a
MODEL-GAP Cannot be routed to any of the above; triggers §12 revision. §12

14. Open questions for the maintainers

Required while (inferred) tags remain. Wave 1 is the load-bearing set; subsequent waves can follow once wave 1 is processed.

Wave 1 — scope and load-bearing defaults

  • 14-Q1 — modules/echo/ scope. Proposed answer: mod_echo is example/test-only and lives in §3 alongside modules/test/ and modules/examples/. Confirm or correct. Lands in §3.
  • 14-Q2 — Support-binary scope. Proposed answer: suexec is in §2; the rest (htpasswd, htdbm, htdigest, ab, htcacheclean, rotatelogs, logresolve, fcgistarter) are admin-side CLI tools, in scope only for issues triggerable by operator-typical usage, with attacker-supplied input to them being OUT-OF-MODEL: trusted-input. Is that right? Lands in §3.
  • 14-Q9 — Module in-scope set. Proposed answer: every module under modules/ that is not in experimental/, test/, examples/, echo/ is in-scope under this document, regardless of distribution packaging choices. Is there a module the PMC considers "shipped but not supported for security purposes" that I should move to §3? Lands in §2 and §3.
  • 14-Q10 — Default MPM in 2.4.x. Proposed answer: event is the default MPM on Unix in 2.4.x; on Windows, winnt (which is the only choice). Confirm. Lands in §5a.
  • 14-Q11 — AllowOverride None is the supported posture. Proposed answer: the secure default (since 2.3.9) is the supported production posture; reports against attacker-writable .htaccess under an operator-enabled AllowOverride All are OUT-OF-MODEL: trusted-input. Confirm. Lands in §5a and §13.
  • 14-Q12 — Require all denied is recommended, not default. This is the insecure-default case in SKILL.md §5a. The recommendation is documented; the ship default (no top-level Directory "/" deny) is permissive. Is a report against the permissive default VALID (operators are not expected to add the deny), or OUT-OF-MODEL: trusted-input (operators are expected to add it before exposing the server)? Proposed answer: the project documents the deny as a recommendation, not as a hard precondition, so it is a §10 operator duty; reports against the permissive default are OUT-OF-MODEL: trusted-input. Lands in §5a, §10, §13.
  • 14-Q17 — §8 properties. I have phrased §8.1, §8.3, §8.5, §8.6, §8.7, §8.8 as inferences from documentation absence. Could you mark each one as (a) yes, this is a claim httpd makes; (b) yes but with the following condition; or (c) no, the project does not claim this? Lands in §8.
  • 14-Q21 — SSLProxyVerify default. Proposed answer: the default is none; a reverse-proxy operator who terminates TLS at httpd and then re-originates plaintext-or-unvalidated TLS to a backend is doing so by their own choice (§10), not via a defect. Lands in §9, §10, §11.

Wave 2 — adversary model and side channels

  • 14-Q3 — Side channels. Proposed answer: side channels (timing, microarchitectural, cache, acoustic) are explicitly out of the adversary model. Confirm. Lands in §3, §7, §9.
  • 14-Q4 — Backend trust in proxy mode. Proposed answer: backends are semi-trusted (operator chose them) but their response bytes are arbitrary; backend RCE-via-response into httpd's parsing path is in scope. Is that right? Lands in §4, §6, §7.
  • 14-Q18 — Constant-time comparison. Proposed answer: httpd does not claim constant-time comparison anywhere in code that compares secrets (basic-auth passwords, digest, mTLS post-decoded fingerprints, session tokens). Is that the project's position, or are there spots where the project has committed to constant-time? Lands in §9.
  • 14-Q19 — mod_ratelimit framing. Should mod_ratelimit be called out as a false friend in §9 (it shapes bandwidth, not request rate) or is the docs framing already adequate? Lands in §9.
  • 14-Q20 — mod_remoteip defaults. Proposed answer: mod_remoteip ships not enabled by default; when enabled, it replaces source IP for connections from configured upstreams. The operator is responsible for the upstream list; an overbroad list is operator-misconfiguration, not a bug. Confirm. Lands in §9, §11.

Wave 3 — environment and stability

  • 14-Q5 — OS/2 and NetWare support tier. Proposed answer: OS/2 and NetWare are "compiles but not actively supported for security purposes" in 2.4.x. Reports against mpmt_os2 or os/netware/ are out-of-tier and accepted at maintainer discretion. Confirm or correct. Lands in §2, §5.
  • 14-Q6 — 32-bit platform support. Proposed answer: 32-bit platforms remain in the supported set; integer-overflow regressions on 32-bit are in scope. Confirm. Lands in §5.
  • 14-Q7 — Clock assumptions. Proposed answer: httpd assumes a near-monotonic system clock; large clock jumps may produce auth/session/cert-validity weirdness but are not an adversarial input. Lands in §5.
  • 14-Q8 — Listen and listening sockets. Proposed answer: every Listen is a network exposure under operator control; binding to 0.0.0.0/:: is operator's choice. Confirm there's no implicit listener the operator is not in control of. Lands in §5.
  • 14-Q13 — Default FollowSymLinks vs SymLinksIfOwnerMatch. Confirm the upstream default and that the documented TOCTOU caveat is the threat-model position. Lands in §5a, §11.
  • 14-Q14 — UserDir ship default. Confirm whether UserDir is enabled by default or whether modern packaging effectively ships it disabled. Lands in §5a.
  • 14-Q15 — ProxyRequests default and §11 framing. Confirm that ProxyRequests Off is the default and that the open-proxy case is §11 misuse only. Lands in §5a, §11.
  • 14-Q16 — Mutex default per platform. Confirm whether the default mutex backend differs by platform and whether the difference matters to the model. Lands in §5a.

Wave 4 — meta

  • 14-Q22 — §11a expansion. The §11a list is sparse and inferred. What scanner/AI/fuzzer reports do you most often close as non-findings against httpd? Anything I should add? Lands in §11a.
  • 14-Q23 — Coexistence with security_tips.html and impact_levels.html. This document is structurally a threat model; security_tips.html is an operator hardening guide; impact_levels.html defines severity. Should this document be (a) a new top-level page on httpd.apache.org, (b) merged into the security/ tree, (c) shipped only as a tooling input? Lands in §1.
  • 14-Q24 — Document ownership. Who is the right PMC reviewer for ratifying §8 and §9?

15. Machine-readable companion

A YAML sidecar suitable for automated triage is provided alongside as httpd-2.4.x-threat-model.yaml. It re-encodes the §2 component-family table, the §6 trust table, the §5a knobs with maintainer-stance once known, the §8 properties with severity tier and violation symptom, the §9 disclaimers and false friends, the §11a non-findings, and the §13 dispositions. The prose document remains canonical; the sidecar is regenerated when the prose changes.


Appendix A — Back-map: project's own security artifacts → this document

Source statement Source artifact Section here
"all networked servers are subject to denial of service attacks…" security_report.html §3, §9
"philosophy is to avoid any attacks which can cause the server to consume resources in a non-linear relationship to the size of inputs" security_report.html §8.2
Severity definitions (Critical / Important / Moderate / Low) impact_levels.html §8 preamble
ServerRoot permissions, default-deny, sensitive-file deny, UserDir disabled root, AllowOverride None recommendation security_tips.html §10, §5a, §11
DoS mitigations: RequestReadTimeout, TimeOut, KeepAliveTimeout, LimitRequest*, MPM choice, AcceptFilter security_tips.html §10
Firewall is the most effective anti-DoS tool; DDoS is out of scope security_tips.html §3, §10
CGI / dynamic-content trust statements security_tips.html §3, §9, §10
Embedded scripting modules "run under the identity of the server itself" security_tips.html §9
SSI risks and IncludesNOEXEC security_tips.html §11
Location vs Directory precedence warning security_tips.html §11
Merging-of-sections caveat security_tips.html §11
suEXEC opt-in, configuration responsibility, PATH warning, code-modification warning suexec.html §5a, §9, §10
Module classification: experimental / test / examples / echo / production families modules/README §2, §3
Version stability commitments within 2.4.x VERSIONING §1, §8.9
Cryptographic export classification and mod_ssl framing README §2, §5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment