Skip to content

One-time OAuth login nonce for shared-playground logins (cubic P1) - #36

Merged
tpaulshippy merged 2 commits into
mainfrom
fix/login-nonce-shared-playground
Oct 20, 2026
Merged

tpaulshippy merged 2 commits into
mainfrom
fix/login-nonce-shared-playground

Conversation

@tpaulshippy

@tpaulshippy tpaulshippy commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Addresses the P1 from cubic's post-merge review of #35: bare playground ids are public, so the cookie==state CSRF check was vacuous on the member login path. Logins started from a bare id now carry an unguessable nonce echoed in an HttpOnly cookie; the callback requires the two to match and consumes the nonce. Legacy/bearer states unchanged. Tests in tests/sharing-canonical.test.ts cover the attack, the fixed flow, nonce single-use, and legacy compat.


Summary by cubic

Fixes a login CSRF vulnerability where shared-playground logins started from a bare (public) playground id could be replayed cross-browser, letting an attacker link their own GitHub account into a victim's member slot.

Logins from a bare id now carry an unguessable one-time nonce in an HttpOnly cookie; the callback requires the nonce to match the OAuth state and expires the cookie once the login is consumed, so a captured state can't be replayed. Legacy and bearer states are already unguessable and are unchanged.

Tests cover the attack (bare state without a nonce rejected even for valid members), the fixed flow, nonce single-use, and legacy compatibility.

Written for commit 8cd4b57. Summary will update on new commits.

View guided diff Turn on auto-fix

Bare playground ids are public, so the cookie==state CSRF check was
vacuous on the member login path: an attacker could authorize their own
account and lure a member's browser to the callback, linking the
attacker's token into the victim's member slot. Logins started from a
bare id now carry an unguessable nonce echoed in an HttpOnly cookie;
the callback requires the two to match and consumes the nonce.
Legacy/bearer states are unguessable and unchanged.

Tests cover the attack (bare state without nonce rejected even for
members), the fixed flow, nonce single-use, and legacy compat.

@cubic-dev-ai cubic-dev-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.

All reported issues were addressed across 2 files

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread tests/sharing-canonical.test.ts Resolved
Comment thread src/index.ts Resolved
@tpaulshippy
tpaulshippy merged commit fdb70c0 into main Oct 20, 2026
3 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