Skip to content

Deploy: production proxy-trust chain unsolved — silently disables #144 HSTS and the #143 per-IP login limiter #260

Closed

Description

@mforce

Deployment-readiness gap (#244), BLOCKER — flagged independently by all 3 reviewers.

Problem

Behind any reverse proxy / edge (the production topology terminates TLS at an
edge and forwards plain HTTP to the container), the app never learns the original
request was HTTPS or who the real client is unless the immediate proxy is
trusted. Two already-"hardened" controls silently break when the trusted-proxy
list is empty:

The compose stack already ships a sane default (TRUSTED_PROXY_CIDR=172.16.0.0/12
in deploy/.env.example + docker-compose.yml); the gap is that a real deploy
must set the correct immediate-proxy CIDR for its edge, and leaving it empty is
unsafe.

Fix (app-side, portable)

The app already reads the trusted-proxy list from config — keep that, and make an
empty TrustedProxies fail loud in Production (refuse to serve with inert
HSTS / a collapsed limiter) so a misconfigured deploy can't silently ship without
the controls. The concrete CIDR for the chosen edge is deploy-repo config.

Verify

  • curl -I https://<prod> shows Strict-Transport-Security.
  • A forged X-Forwarded-For from a non-proxy peer is ignored.
  • Two distinct clients hit two distinct login buckets (11 logins from client A
    does not 429 client B).

Part of the #244 deployment-readiness audit; tracked in epic #15.

Activity

  1. added 2 commits that reference this issue on Jul 30, 2026
  2. mforce commented on Jul 30, 2026

    @mforce
    OwnerAuthor

    App-side landed in PR #293 (merged): the serving process now fails boot loudly in Production when RateLimiting:TrustedProxies is empty, with an AllowNoTrustedProxies opt-out for a deliberate direct-TLS deploy. This closes the silent-degradation vector that made this a BLOCKER — HSTS (#144) and the per-IP limiter (#143) can no longer be inert without the boot failing.

    Remaining is deploy-side and belongs in a separate deployment/ops repo: set the concrete edge/proxy CIDR for the chosen host (the guard now enforces that it's present). Leaving this open to track that one config step; safe to close once the CIDR is wired in that deployment repo (or now, since the app-side protection is complete).

  3. mforce commented on Jul 30, 2026

    @mforce
    OwnerAuthor

    Closing as a duplicate of the deploy-side work now tracked in a separate deployment/ops repo (set the trusted-proxy CIDR for the chosen edge).

    The app-side is complete and merged (PR #293): an empty RateLimiting:TrustedProxies now fails the Production boot (with an AllowNoTrustedProxies opt-out), so the silent-degradation vector that made this a BLOCKER is closed. The only remaining work — setting the concrete edge CIDR — is host config and lives in that separate deployment repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions