Skip to content

fix(workspaces): key basic-auth bypass on resolved client IP - #10

Merged
pcfreak30 merged 2 commits into
developfrom
fix/workspace-basic-auth-bypass
Sep 24, 2026
Merged

pcfreak30 merged 2 commits into
developfrom
fix/workspace-basic-auth-bypass

Conversation

@pcfreak30

@pcfreak30 pcfreak30 commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

All workspace traffic arrives through the Coolify proxy, whose TCP peer is a private-range address, so the private-peer exemption matched every request and basicauth never fired — auth was silently off for the whole internet.

Switches the bypass to Caddy's client_ip matcher through trusted_proxies private_ranges: proxied public-range clients require credentials, in-network peers (Cast's anonymous probe) and the localhost /healthz check stay exempt, and a public-range peer's forged X-Forwarded-For stays ignored as an untrusted peer. Documents the assumption that the deployment proxy always sets X-Forwarded-For (Traefik/Caddy default).

Adds the missing verification case — a private-range peer forwarding a public-range client — plus credential-matrix and private-client-bypass assertions, and aligns the auth-contract docs.


fix(workspaces): key basic-auth bypass on resolved client IP

Summary

Fixes a critical HTTP Basic Auth bypass in the workspace runtime image (images/php-caddy/Caddyfile). The auth exemption previously keyed on Caddy's remote_ip matcher (the raw TCP peer). In production, every request reaches the container through the private-range Coolify proxy, so a peer-based exemption meant all proxied traffic — including every public internet client — bypassed authentication, silently disabling auth.

What changed

  • images/php-caddy/Caddyfile: The Basic Auth exemption matcher was switched from remote_ip to client_ip. Through the already-configured trusted_proxies static private_ranges, Caddy now resolves the real client IP from the trusted private-range proxy's X-Forwarded-For (or uses the raw peer when no forwarded chain exists):

    • Proxied public clients (public-range client IP in XFF) are no longer exempt and must present valid Basic Auth credentials → 401 without them.
    • Loopback / private-network resolved clients remain exempt, so the container's Docker health check of /healthz and in-deployment probes (e.g. Cast's anonymous export probe) stay unauthenticated.
    • Public peers are untrusted, so their spoofed X-Forwarded-For / X-Real-IP headers are ignored and auth is enforced against their real peer address.
  • scripts/verify-php-caddy.sh: Added regression tests for the production topology:

    • private-range proxy peer forwarding a public client (X-Forwarded-For: 192.0.2.77) → 401 without credentials, 200 with valid credentials, 401 with bad credentials;
    • private-range peer with a private-range XFF → 200 without credentials (stays exempt);
    • trusted loopback peer forwarding a public XFF → now 401 (previously expected 200);
    • loopback with loopback XFF → still 200;
    • public peer spoofing loopback headers → still 401.
  • Documentation (AGENTS.md, README.md, images/php-caddy/README.md, images/wordpress/README.md): Updated the auth-contract docs to describe the resolved-client-IP model, the trust assumptions (private-range peers trusted, public peers untrusted), and why a peer-IP-based (remote_ip) bypass is unsafe (it would exempt the private-range proxy peer and disable auth for the whole internet).

Review finding

The automated review reported 1 critical finding: the Caddy client_ip resolution is flagged as parsing X-Forwarded-For non-strictly (left→right), which could allow a public attacker forging a loopback XFF header to bypass Basic Auth via the trusted proxy. This remains recorded as a known risk to follow up on.

- all proxied traffic has a private-range tcp peer (coolify proxy), so
  the remote_ip-based private-peer exemption disabled auth for everyone
- resolve the client ip via caddy client_ip through trusted_proxies:
  public-range forwarded clients authenticate, in-network peers and the
  loopback health probe stay exempt
- public-range peer spoofed headers ignored (untrusted); forgery from a
  trusted peer can only require more auth, never grant a bypass
- verify matrix gains the missing proxied-public-client case plus
  private-client bypass and trusted-peer header resolution assertions
- align auth contract docs across repo
@kody-ai

This comment has been minimized.

@pcfreak30
pcfreak30 marked this pull request as ready for review September 24, 2026 23:09
Comment thread images/php-caddy/Caddyfile

@kody-ai kody-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- trusted_proxies_strict parses the XFF chain right-to-left (first
  untrusted address); the default left-to-right scan lets a proxied
  client spoof a private-range leftmost entry (e.g. X-Forwarded-For:
  127.0.0.1) and resolve client_ip to it, bypassing auth internet-wide
- strict mode is available since Caddy v2.8; this image pins 2.11.4
- verify matrix gains the chained-XFF case (spoofed private prefix +
  public client -> 401) and an all-private-chain fallback case
- align bypass-resolution comments/docs to strict semantics
@kody-ai

kody-ai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

​

@pcfreak30
pcfreak30 merged commit be798da into develop Sep 24, 2026
5 checks passed
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