|
| 1 | +# Debug-only environment variables |
| 2 | + |
| 3 | +This document inventories environment variables that the libhttpserver |
| 4 | +runtime reads. **None of these are meant to be set in production.** |
| 5 | +All are silent unless explicitly enabled; the library emits a one-shot |
| 6 | +`SECURITY WARNING` to stderr (and to the user's `log_error` callback, |
| 7 | +when wired) the first time `webserver::start()` observes a set |
| 8 | +variable. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## `LIBHTTPSERVER_DEBUG_DUMP_REQUEST_BODY` |
| 13 | + |
| 14 | +| Field | Value | |
| 15 | +| --- | --- | |
| 16 | +| Introduced | TASK-074 (June 2026) | |
| 17 | +| Replaces | The prior compile-time `#ifdef DEBUG` guard in `src/detail/webserver_body_pipeline.cpp` | |
| 18 | +| Read by | `httpserver::detail::debug_dump_request_body_opted_in()` (cached in a function-local static) | |
| 19 | +| Independent of | Compile-time `DEBUG` / `NDEBUG`. The runtime check is the only gate. | |
| 20 | + |
| 21 | +### Effect |
| 22 | + |
| 23 | +When set to any non-empty, non-`"0"` value, every inbound request body |
| 24 | +chunk is written verbatim to `stdout`, prefixed by `Writing content: `, |
| 25 | +from the body pipeline in `src/detail/webserver_body_pipeline.cpp`. |
| 26 | + |
| 27 | +### Risk |
| 28 | + |
| 29 | +Raw request bodies routinely contain: |
| 30 | +- Basic-auth credentials (when sent in the body rather than the header), |
| 31 | +- form-posted passwords (`application/x-www-form-urlencoded` with a |
| 32 | + `password=` field), |
| 33 | +- session cookies, |
| 34 | +- CSRF tokens, |
| 35 | +- PII (email addresses, names, IDs, addresses). |
| 36 | + |
| 37 | +The `http_request::operator<<` redaction policy introduced in TASK-057 |
| 38 | +does **not** cover this code path -- bytes are written verbatim. Treat |
| 39 | +any process where this variable is set as a credential-leaking |
| 40 | +surface (CWE-532: Insertion of Sensitive Information into Log File). |
| 41 | + |
| 42 | +### Startup signal |
| 43 | + |
| 44 | +The library emits a single `SECURITY WARNING` line to stderr at the |
| 45 | +first `webserver::start()` call after the variable is observed. The |
| 46 | +exact line is: |
| 47 | + |
| 48 | +``` |
| 49 | +[libhttpserver] SECURITY WARNING: LIBHTTPSERVER_DEBUG_DUMP_REQUEST_BODY is set. Raw request bodies will be written to stdout, including credentials, session cookies, and PII. Unset the variable for production deployments. See docs/debug-env-vars.md. |
| 50 | +``` |
| 51 | + |
| 52 | +The same line is forwarded to the owning webserver's `log_error` |
| 53 | +callback when one is wired via `create_webserver().log_error(...)`. The |
| 54 | +forwarding is best-effort: an exception from the callback is swallowed |
| 55 | +so a misconfigured logger cannot abort daemon startup. |
| 56 | + |
| 57 | +Multiple `webserver` instances constructed in the same process share a |
| 58 | +process-wide print-once flag, so the warning is emitted exactly once |
| 59 | +per process. |
| 60 | + |
| 61 | +### How to disable |
| 62 | + |
| 63 | +```sh |
| 64 | +unset LIBHTTPSERVER_DEBUG_DUMP_REQUEST_BODY |
| 65 | +``` |
| 66 | + |
| 67 | +then restart the process. The value is cached in a function-local |
| 68 | +static on first request, so a mid-process `unsetenv()` has no effect. |
| 69 | + |
| 70 | +### Spot-check: release build with `-DDEBUG` accidentally set |
| 71 | + |
| 72 | +The runtime check is the only gate; the env var must be explicitly set |
| 73 | +for the dump to fire, regardless of the compile-time `DEBUG` / |
| 74 | +`NDEBUG` posture. A release binary built with `-DDEBUG` accidentally |
| 75 | +defined therefore still does not leak credentials/PII unless the |
| 76 | +operator opted in. |
| 77 | + |
| 78 | +--- |
| 79 | + |
| 80 | +## Adding new debug env vars |
| 81 | + |
| 82 | +When introducing a new `LIBHTTPSERVER_*` debug environment variable: |
| 83 | + |
| 84 | +1. Read it once via a function-local static (cached, race-free C++ |
| 85 | + memory model semantics). |
| 86 | +2. Add a one-shot stderr warning in `webserver::start()` naming the |
| 87 | + risk explicitly. |
| 88 | +3. Document the variable, its risk, and its startup signal here. |
| 89 | +4. Cross-reference the entry from `specs/architecture/10-observability.md`. |
0 commit comments