Decide whether Edge Router should emit HSTS, on the admin host and optionally for proxied hosts #59

Open
opened 2026-10-26 15:38:20 +00:00 by james.oates · 1 comment
Owner

The cookie half of this is fixed in 78ae254, alongside #69. Rescoped to the HSTS question this issue raised as the separate decision it is.

api.rs set the cookie's Secure flag from the IsHttps extension, which tls.rs inserts only when ER itself terminated TLS — so the supported CDN/tunnel topology shipped the cookie without it. There are now not two definitions of "is this request HTTPS" but one: access::request_is_https (the TLS marker, or a trust_forwarded_for listener reporting X-Forwarded-Proto: https), used by the redirect, the session-route guard and the cookie. As this issue noted, the trust gate from f02af79 is what made that safe, and spoofing can only ever add Secure.

What remains: HSTS

There is no Strict-Transport-Security header anywhere in src/. The attack this issue described is only partly closed by the cookie fix: Secure stops er_session being sent over http://, but nothing stops the browser trying plaintext in the first place, and a login over http:// is now refused rather than redirected (#69), which a user may read as a broken dashboard rather than a scheme problem.

Decisions needed:

  1. Emit HSTS on the admin host? Lowest-risk case — it is Edge Router's own surface, and an operator reaching the dashboard over HTTPS should keep doing so. Still pins the host for max-age.
  2. Allow it for proxied hosts? Much bigger. An operator-set HSTS on a shared parent domain has long-lived consequences for every sibling name, especially with includeSubDomains. If it is offered at all it should be per-service, opt-in, with max-age explicit rather than defaulted, and the docs should say plainly that it cannot be un-done quickly.
  3. Preload? Probably never from Edge Router's config.

Worth doing (1) and deferring (2) until someone asks.

**The cookie half of this is fixed** in `78ae254`, alongside #69. Rescoped to the HSTS question this issue raised as the separate decision it is. `api.rs` set the cookie's `Secure` flag from the `IsHttps` extension, which `tls.rs` inserts only when ER itself terminated TLS — so the supported CDN/tunnel topology shipped the cookie without it. There are now not two definitions of "is this request HTTPS" but one: `access::request_is_https` (the TLS marker, or a `trust_forwarded_for` listener reporting `X-Forwarded-Proto: https`), used by the redirect, the session-route guard and the cookie. As this issue noted, the trust gate from `f02af79` is what made that safe, and spoofing can only ever *add* `Secure`. ## What remains: HSTS There is no `Strict-Transport-Security` header anywhere in `src/`. The attack this issue described is only partly closed by the cookie fix: `Secure` stops `er_session` being sent over `http://`, but nothing stops the browser *trying* plaintext in the first place, and a login over `http://` is now refused rather than redirected (#69), which a user may read as a broken dashboard rather than a scheme problem. Decisions needed: 1. **Emit HSTS on the admin host?** Lowest-risk case — it is Edge Router's own surface, and an operator reaching the dashboard over HTTPS should keep doing so. Still pins the host for `max-age`. 2. **Allow it for proxied hosts?** Much bigger. An operator-set HSTS on a shared parent domain has long-lived consequences for every sibling name, especially with `includeSubDomains`. If it is offered at all it should be per-service, opt-in, with `max-age` explicit rather than defaulted, and the docs should say plainly that it cannot be un-done quickly. 3. **Preload?** Probably never from Edge Router's config. Worth doing (1) and deferring (2) until someone asks.
james.oates added this to the v2.1 milestone 2026-10-26 17:53:26 +00:00
james.oates changed title from Session cookie lacks Secure behind a TLS-terminating proxy, and there is no HSTS to Decide whether Edge Router should emit HSTS, on the admin host and optionally for proxied hosts 2026-10-27 09:44:23 +00:00
james.oates removed this from the v2.1 milestone 2026-10-27 10:30:10 +00:00
Author
Owner

Deferred: not requested (James, 2026-10-27). Milestone removed, left open.

His rule, which now applies to this repo generally: don't optimise early. If nothing asks for a thing and it brings no real benefit, don't build it — and don't put it forward as a decision either. Defects with a real attack or failure path still get fixed; #63 and #69 are the examples.

HSTS is a feature nobody has asked for. The cookie half of this issue was a real defect and is fixed (78ae254): Secure is now set whenever the client's hop was TLS, including behind a trusted terminating proxy. What is left is header emission, which guards against a browser trying http:// first — and every fleet host reaches the dashboard over TLS, while a cleartext login is now refused outright rather than redirected (#69).

If it is ever picked up, the decisions in the comment above still stand: admin host only is the low-risk case, proxied hosts are a much larger commitment because an operator-set HSTS on a shared parent domain cannot be undone quickly, and preload should probably never come from Edge Router's config.

**Deferred: not requested (James, 2026-10-27).** Milestone removed, left open. His rule, which now applies to this repo generally: don't optimise early. If nothing asks for a thing and it brings no real benefit, don't build it — and don't put it forward as a decision either. Defects with a real attack or failure path still get fixed; #63 and #69 are the examples. HSTS is a feature nobody has asked for. The cookie half of this issue was a real defect and is fixed (`78ae254`): `Secure` is now set whenever the client's hop was TLS, including behind a trusted terminating proxy. What is left is header emission, which guards against a browser trying `http://` first — and every fleet host reaches the dashboard over TLS, while a cleartext login is now refused outright rather than redirected (#69). If it is ever picked up, the decisions in the comment above still stand: admin host only is the low-risk case, proxied hosts are a much larger commitment because an operator-set HSTS on a shared parent domain cannot be undone quickly, and preload should probably never come from Edge Router's config.
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
IsoHex/edge-router#59
No description provided.