Skip to content

Web editor: cap a session at 8 hours and name its cookie __Host-s - #156

Merged
Skeyelab merged 2 commits into
mainfrom
web-session-cap
Oct 27, 2026
Merged

Skeyelab merged 2 commits into
mainfrom
web-session-cap

Conversation

@Skeyelab

Copy link
Copy Markdown
Member

Hardening left open from #98's web-editor reviews.

  • Absolute cap: a session still ends after 15 minutes without a request, and now also 8 hours after login, however active it is. Before, activity kept it alive forever, so a stolen cookie in a tab left open kept working. Session.startMs and kSessionMaxMs in lib/web; the check is wrap-safe, like the idle check.
  • __Host- prefix: the cookie is now __Host-s. The browser only accepts it from a secure origin with Path=/ and no Domain, so another host on the LAN, or a subdomain, can't plant one. The parser no longer reads a plain s cookie. After updating, a logged-in browser logs in again once.

Red run (pio test -e native -f test_web, with only the constant added)

test/test_web/test_web.cpp:46: test_the_session_token_comes_from_its_cookie: Expected '0123456789abcdef0123456789abcdef' Was ''	[FAILED]
test/test_web/test_web.cpp:86: test_activity_does_not_keep_a_session_past_its_cap: Expected FALSE Was TRUE	[FAILED]

Green: 70/70 native tests pass, and crowpanel-dev builds.

Not checked yet

  • On the panel, a curl login (Set-Cookie: __Host-s=…, then a request with it). I'll run it when the panel is free.
  • The 8 h cap itself is checked only by the host test.

… and its cookie is __Host-s

Assisted-by: Claude Code:claude-opus-5-5
…t come back after millis() wraps (#156 reviews)

Assisted-by: Claude Code:claude-opus-5-5
@Skeyelab

Copy link
Copy Markdown
Member Author

Reviews (AppSec and Embedded Firmware Engineer): both FIX, same finding.

Session times were on the 32-bit millis(), so about 49.7 days after the last request both checks came out small again and an unused cookie worked again: for up to 15 min, extendable to 8 h. The idle timeout already had this hole.

Fixed in 189a96f: Session stores 64-bit ms from esp_timer_get_time() / 1000, which doesn't wrap in practice.

Red run of the new test, which uses the reviewer's case (touch at 1 h, request at 1 h + 2^32 ms + 1 min):

test/test_web/test_web.cpp:97: test_a_session_left_unused_for_49_days_stays_ended: Expected FALSE Was TRUE	[FAILED]

My first try at this test passed before the fix, because the uint32 parameters truncated the time. I replaced it with the case above. The old "millis() wraps" check in the existing test now crosses 2^32 instead.

Green: 71/71, and crowpanel-dev builds. Re-reviews requested.

@Skeyelab

Copy link
Copy Markdown
Member Author

AppSec re-review of 189a96f: PASS.

  • All three session call sites use nowMs() (64-bit, from esp_timer).
  • The differences can't underflow.
  • Login and logout and the __Host- attributes are unchanged.
  • The new test fails on the old 32-bit code.

Still pending: the firmware re-review, a panel login check, and a real-browser check of __Host-s on the self-signed https origin.

@Skeyelab

Copy link
Copy Markdown
Member Author

Embedded Firmware Engineer re-review of 189a96f: PASS.

  • The 64-bit math and the esp_timer include are right.
  • nowMs() is used at all three session call sites. The other millis() uses are local timeouts within one call.
  • The tests check the right edges.

Both reviews have passed. Auto-merge goes on after the panel login check (agent3 has the panel now).

@Skeyelab

Copy link
Copy Markdown
Member Author

Panel login check: skipped. The panel now runs Eric's real setup with his own admin password, which I don't use. Main's call: merge on the two reviews alone. Not checked on a device:

  • that a browser accepts __Host-s from the panel's self-signed https IP; Eric's first login after the update will show it;
  • that an already logged-in browser has to log in once more (expected).

@Skeyelab
Skeyelab merged commit 12aad0a into main Oct 27, 2026
6 checks passed
@Skeyelab
Skeyelab deleted the web-session-cap branch October 27, 2026 00:02
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