Only trust Authelia identity headers from the proxy #16

Merged
jared merged 1 commits from trusted-proxy-auth into main 2026-11-10 13:28:50 -05:00
Owner

Closes #3

Identity headers sent to the container directly, rather than through the Authelia-protected proxy, were trusted. This change accepts them only from configured proxy addresses.

Changes

  • New auth.trusted_proxies setting: a list of addresses or CIDR ranges. The Remote-* headers are ignored unless the request came from one of them.
  • Source address: behind the local nginx, it is nginx's X-Real-IP. If gunicorn is reached directly, it is the peer address.
  • Fails closed: with no entries, nobody is trusted. Invalid entries are logged and skipped.
  • Logging: rejected identity headers are logged.
  • Avatar endpoint: /api/avatar now uses the same check.
  • README: documents the setting and corrects the NPM forward target. NPM forwards to nginx, not to gunicorn.

The container's nginx site has a matching change in pve-infra.

Testing

  • 10 new tests cover trusted and untrusted sources, fail-closed behaviour, CIDR and invalid entries, logging, and the avatar endpoint.
  • All 224 tests, flake8 and bandit -ll pass.

🤖 Generated with Claude Code

Closes #3 Identity headers sent to the container directly, rather than through the Authelia-protected proxy, were trusted. This change accepts them only from configured proxy addresses. ## Changes - **New `auth.trusted_proxies` setting:** a list of addresses or CIDR ranges. The `Remote-*` headers are ignored unless the request came from one of them. - **Source address:** behind the local nginx, it is nginx's `X-Real-IP`. If gunicorn is reached directly, it is the peer address. - **Fails closed:** with no entries, nobody is trusted. Invalid entries are logged and skipped. - **Logging:** rejected identity headers are logged. - **Avatar endpoint:** `/api/avatar` now uses the same check. - **README:** documents the setting and corrects the NPM forward target. NPM forwards to nginx, not to gunicorn. The container's nginx site has a matching change in pve-infra. ## Testing - 10 new tests cover trusted and untrusted sources, fail-closed behaviour, CIDR and invalid entries, logging, and the avatar endpoint. - All 224 tests, `flake8` and `bandit -ll` pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jared added 1 commit 2026-11-10 13:23:51 -05:00
Only trust Authelia identity headers from the proxy
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (flake8) (push) Successful in 1m9s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m33s
Test / Python Tests (pytest) (push) Successful in 1m54s
Lint / Python (flake8) (pull_request) Successful in 1m19s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 1m16s
Test / Python Tests (pytest) (pull_request) Successful in 1m29s
5c4e4dc099
Remote-User/Name/Email/Groups were read from every request, so a LAN host
connecting to the container directly could claim any user and group. Add
auth.trusted_proxies and ignore those headers unless the request came from
one of them: the X-Real-IP the local nginx sets, or the peer address when
gunicorn is reached directly. With nothing configured, nobody is trusted.
Rejected attempts are logged, and /api/avatar now uses the same check.

The container's nginx site blanks the same headers for non-NPM sources
(pve-infra 4e3ab7c).

Closes #3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jared merged commit 085c488f7b into main 2026-11-10 13:28:50 -05:00
jared deleted branch trusted-proxy-auth 2026-11-10 13:28:51 -05:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/gandalf#16