Skip to content

Web authentication

Defang Agent edited this page Oct 28, 2026 · 3 revisions

Web authentication

Each Linux user has one web password and one Caddy Basic-auth bypass cookie. The cookie name contains the user name (__Host-agent_box_auth_<user>), and Caddy checks its secret value before the Basic-auth fallback. The root page uses the configured default user. The workspace, terminal, settings page, and downloads route for that user use the same cookie. A working root page therefore does not establish that a different user's route has a valid cookie or that a typed Basic password is correct.

The cookie has Path=/, Secure, HttpOnly, and SameSite=Lax, and it has no Domain attribute. The __Host- prefix makes browsers enforce Secure, Path=/, and the absence of Domain, so the cookie is sent only to the exact box hostname that set it. This is a security boundary: unrelated boxes share parent suffixes such as ip.sslip.io and ip.domainstation.com, and an auth cookie scoped to one of those parents would reach sibling boxes.

Lax lets a browser send the cookie on a top-level navigation back from another site. Strict withholds it on a fresh cross-site navigation, causing an unnecessary Basic challenge even when the user has signed in. Lax still withholds the cookie from cross-site POSTs. The settings daemon separately checks the origin of every state-changing POST because browsers can send cached Basic credentials on those requests; cookie SameSite does not protect Basic auth. The portal handoff session cookie uses the same __Host-, Path=/, Secure, and no-Domain contract, and is also Lax so it survives the cross-site redirect after the portal POST.

basic_auth returns a 401 challenge with no body or Content-Type. With the site's X-Content-Type-Options: nosniff, a browser may offer that response as a download when the password dialog is dismissed. The shared Caddy error handler supplies a short HTML 401 page and leaves WWW-Authenticate intact. The settings daemon likewise sends HTML for an invalid portal session while clearing that session cookie. A 401 on the downloads route must not inherit its Content-Disposition: attachment header.

Browser history restoration may send a Strict cookie in some circumstances. The Lax change fixes fresh cross-site returns; a Basic prompt on browser Back still needs the actual request and browser behavior to identify its cause.

See issue #746 for the download symptom, issue #117 for the settings POST origin check, and issue #771 for the remaining browser Back investigation. Issue #813 records the host-only cookie regression checks.

Frontend response identifiers

The managed Caddy routes remove Server and Via response headers, including headers supplied by an upstream. HTTP redirects are explicit: Caddy's automatic redirects bypass site header handlers, so auto_https disable_redirects and a catch-all HTTP redirect preserve HTTPS upgrades without that disclosure. An unmatched HTTPS Host gets a sanitized 404. Named sites, including imported ~/sites virtual hosts, take precedence over the fallback routes; those custom sites own their HTTPS response headers.

Error chains need their own deletion handler: removing a header from the normal route does not cover an upstream failure handled by Caddy. Keep these deferred header deletions separate from the immediate management security headers, or they can overwrite the downloads route's stricter CSP. The caddy-server-header native check requests both backend renders and verifies redirects, auth challenges, upstream responses, errors and download restrictions. See issue #962.

Clone this wiki locally