Skip to content

fix(litestar): stop logging request and response bodies by default - #162

Merged
lesnik512 merged 12 commits into
mainfrom
fix/litestar-middleware-logging-body-leak
Aug 10, 2026
Merged

fix(litestar): stop logging request and response bodies by default#162
lesnik512 merged 12 commits into
mainfrom
fix/litestar-middleware-logging-body-leak

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Litestar's StructlogPlugin was registered with only structlog_logging_config set, so Litestar's default enable_middleware_logging=True installed LoggingMiddleware with a config that logs full request and response bodies. Reproduced on litestar 2.24.0: a POST /login logged its password verbatim, and each offline Swagger asset was logged as a ~150 KB response body.

Access logging is now off by default, matching every other bootstrapper. litestar_logging_middleware_enabled=True turns it back on with metadata-only fields and infrastructure-path exclusions; litestar_logging_middleware_config replaces those defaults wholesale.

Design, rationale and the rejected alternatives: planning/changes/2026-08-10.01-litestar-middleware-logging.md. Release notes: planning/releases/1.4.0.md.

Behavior change — services relying on the HTTP Request / HTTP Response lines lose them until they set the flag. Minor release (1.4.0).

Promoted into architecture/instruments.md; documented in docs/integrations/litestar.md and docs/introduction/configuration.md.

Two defects found while reproducing this are deliberately out of scope and need their own change files:

  • _MemoryLoggerFactoryConfig.log_stream binds sys.stdout at import time, so a process that redirects stdout after importing lite_bootstrap logs to a stale stream.
  • LitestarConfig.application_config defaults to a bare AppConfig() whose request_max_body_size is Empty, and Litestar.from_config() does not apply the 10 MB default Litestar(...) uses, so any body-reading handler 500s.

🤖 Generated with Claude Code

LitestarLoggingInstrument leaves Litestar's LoggingMiddleware defaults in
place, logging full request and response bodies: credentials from API calls
and the whole offline Swagger bundle. Design turns middleware logging off by
default and adds an opt-in flag with metadata-only, path-excluding defaults.
Litestar's StructlogPlugin defaults enable_middleware_logging to True, so
every request body (credentials included) and every response body reached
stdout. Set it from the new litestar_logging_middleware_enabled config field,
which defaults to False, matching the other bootstrappers.
Replace Litestar's LoggingMiddlewareConfig defaults with path, method,
content_type, path_params and status_code. Bodies, headers, cookies and query
strings are where credentials live, so none of them are logged.
Swagger assets, k8s probes and Prometheus scrapes drowned out real traffic.
Build the middleware exclude list from the paths the config already knows,
regex-escaped, skipping empty values and a degenerate root path.
Litestar matches middleware exclude patterns with an unanchored search, so a
bare escaped prefix would suppress access logs for lookalike routes.
Litestar matches exclude patterns with an unanchored search, so a bare
regex-escaped prefix like /custom-health also matched lookalikes such as
/custom-healthy, silently suppressing their access logs. Anchor each
pattern to the path itself or a sub-path.
litestar_logging_middleware_config replaces the hardened defaults wholesale
for services that need their own access-log shape. Setting it while access
logging is off is a silent no-op, so the config warns about it.
Record the recorded-log test strategy, the anchored exclude patterns and the
lookalike-route regression test as realized.
Add planning/releases/1.4.0.md with a prominent behavior-change notice for
the Litestar access-logging default flip (CI requires curated notes for a
stable tag). Document the two new LitestarConfig options in the
configuration reference, expand the litestar.md access-logging subsection
with the excluded-path list, the path/path_params caveat, and a non-header
escape-hatch example, correct the exclude-matching mechanism described in
the design change file against the installed Litestar source, and note that
LitestarConfig now also needs the explicit super() form under slots=True.
Reorder litestar_logging_middleware_config/enabled to keep LitestarConfig's
fields alphabetical, move the shared _login_handler test route into
_post_password so each app that uses it gets its own handler instance
instead of sharing cached signature/state, and add a unit test pinning
_build_logging_middleware_excluded_paths' degenerate-path guard (empty
values, a bare "/", duplicates) and the exclude=None collapse when nothing
survives.
@lesnik512
lesnik512 merged commit 54c8ad9 into main Aug 10, 2026
11 checks passed
@lesnik512
lesnik512 deleted the fix/litestar-middleware-logging-body-leak branch August 10, 2026 16:33
lesnik512 added a commit that referenced this pull request Aug 10, 2026
…#163)

Both were found while fixing the Litestar access-log body leak (#162) and kept
out of it to leave a security fix unencumbered.

- log_stream binds sys.stdout at import, so structlog output ignores a stdout
  the process rebinds before bootstrap, while the root-logger handler follows
  it (lightweight lane).
- Litestar.from_config() skips the request_max_body_size default that
  Litestar.__init__ applies, so every body-reading handler returns 500 unless
  the caller sets the field themselves (full lane). Reported upstream as
  litestar-org/litestar#4296.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant