mirror of
https://github.com/Mudlet/Mudlet
synced 2026-08-13 18:26:27 -04:00
3 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c4849b6651
|
improve: OSC 8 hyperlink handling, and a setting to turn it off (#9731)
#### Brief overview of PR changes/additions - Hardens how OSC 8 link payloads and link text are handled before they are run or displayed; link commands are no longer built by string-formatting remote text into Lua source. - Adds a per-profile setting (General → Game protocols) to turn OSC 8 hyperlinks off, which also reports `0` for every `OSC_HYPERLINKS*` NEW-ENVIRON variable and sends an INFO update if toggled mid-session. - Fixes `selected=` callbacks on `send:` links, which never fired, and keeps emoji and Persian/Arabic/Indic text intact in tooltips and menu labels. #### Motivation for adding to Mudlet Inspired by [conversation](https://discord.com/channels/279748146316312576/1416447642472284261/1535109010066251890) on the MUD Discord and updates to terminal emulators. OSC 8 sequences arrive from the game server — and often from another player whose say/tell text the server relays — so they have to be treated as untrusted input rather than as content the user chose to load. #### Other info (issues closed, discussion etc) New unit tests: `LuaLiteralTest` (28 cases, including an exhaustive sweep over the bracket alphabet, each evaluated in a real Lua 5.1 state) and `UntrustedTextTest` (26 cases covering emoji sequences, non-Latin shaping and the two sanitization policies). There is no automated NEW-ENVIRON coverage anywhere in the repo, so that path was verified manually against a live server instead. **Test case:** 1. `say !osc8-docs` — every documented feature still works. 2. Send a link whose command ends in `]`, e.g. `send:say [OOC]` — clicking sends the literal text (previously the click silently did nothing). 3. Settings → General → Game protocols → uncheck "Enable OSC 8 hyperlinks from the server" — links stop rendering and the server is told without a reconnect; re-check and they return. 4. Send a tooltip or menu label containing a multi-part emoji such as 👨🍳 — it renders normally, not as its component parts. --------- Signed-off-by: Michael Conley <sousesider@gmail.com> |
||
|
|
963b035ab4
|
fix: four security holes in the new browser sign-in (#9713)
#### Brief overview of PR changes/additions Four security fixes to the GMCP `Char.Login` v2 browser sign-in added in #9378 *Add: sign in to supported games using your browser (e.g. Google, Discord, or the game's own account)*, found by the 5.0 QA sweep and reproduced on the wire. The game server is untrusted throughout: Mudlet connects to arbitrary user-specified MUDs. - **A saved sign-in no longer goes out in the clear.** `Char.Login.Reconnect` carries a bearer token that signs into the player's account without their password, and Mudlet replayed it on whatever transport was live at the time - so a sign-in earned over TLS went out over plain telnet on the next connect. It is now refused on a cleartext transport, mirroring the `Char.Login.AuthCode` guard already in the same file; the player is told why and the sign-in falls back to the provider resume or the game's own sign-in screen. - **A server can no longer open browser tabs at will.** The client-driven OAuth path reached `QDesktopServices::openUrl()` with a server-chosen address and no guard at all, once per frame the server sent (5 frames measured, 5 tabs). Both flows now go through one decision point with a budget of one automatic hand-off per connection, refilled whenever the player sends something to the game. The client-driven flow still opens the browser on connect - that is the sign-in the player came for - but a burst of frames buys one tab, not a tab each, and `Char.Login.URL`, which a server may push at any moment, still needs actual input first. - **The OIDC nonce reaches the game, and a `Char.Login.Default` flood no longer buys credential-store churn.** With `"nonce": true` Mudlet generated a nonce and put it in the authorization URL but never sent it on, so the party that actually validates the ID token could not check its `nonce` claim; it now rides in `Char.Login.AuthCode`. Separately each `Char.Login.Default` frame started a fresh credential-store read (a 114 KB flood measured 4002 reads); sign-in attempts are now throttled to one per second, and dropped outright if the connection that scheduled them has gone. #### Motivation for adding to Mudlet All four are new in 5.0 and none was covered by a test, which is why they shipped. The token replay is the serious one: it hands a password-equivalent account credential to anyone on the path. Two decisions worth a second opinion: - The Char.Login 2 draft on Area 51 defines no `nonce` field in `Char.Login.AuthCode`, so this adds one. Without it `"nonce": true` cannot mean anything - nobody is in a position to verify the value. **The spec needs the field added to match.** - The same draft explicitly permits sending the reconnect token over plain telnet ("a server may choose to issue and accept tokens only over `telnets://`"). It does not require a client to, so refusing is conformant, but it is deliberately stricter than the spec. #### Other info (issues closed, discussion etc) Test case: connect a profile with a saved sign-in to a game offering `Char.Login 2` over plain telnet - Mudlet says the connection is not encrypted and hands off to the game's own sign-in screen instead of replaying the token. `GMCPCharLoginTest` gains a TLS-capable stub (embedded self-signed loopback certificate) and a loopback OpenID discovery stub, so the encrypted-transport and client-driven paths are exercised for real rather than assumed. The seven existing token tests move onto it, which is itself the proof that they were previously passing over cleartext. 80/80 `ctest` green. Assisted-by: Claude:claude-opus-5 |
||
|
|
a97186ad5f
|
Add: sign in to supported games using your browser (e.g. Google, Discord, or the game's own account) (#9378)
#### Brief overview of PR changes/additions
Adds client-side support for the GMCP `Char.Login` v2 sign-in flow. When
a game offers it, Mudlet automates sign-in *around the game's own login
screen* — it renders no sign-in UI of its own:
- Hands off to the game's interactive screen with an empty
`Char.Login.Credentials {}` when nothing is stored, so the player picks
a provider (Google, Discord, GitHub, the game's own account, …) as text
on the game's own screen.
- Opens the sign-in URL the server pushes (`Char.Login.URL`) in the
system browser — but only after the player has acted on this connection,
never unprompted.
- Autofills a stored character name + password when the profile has
them.
- Persists and replays the server's reconnect token (`Char.Login.Token`
/ `Char.Login.Reconnect`) for instant, password-less reconnects, with a
"forget saved sign-in" control in Preferences → Connection.
- Resumes the *remembered* provider's browser sign-in without a menu
when a saved token has expired or been revoked (`Char.Login.Credentials
{account, provider}`), falling back to the interactive hand-off only
when no provider is remembered.
- Handles token rotation and multiple devices safely: overwrites the
saved token when the server rotates it, and if another running Mudlet
instance sharing the profile's keychain rotates the token mid-flight,
replays the fresh token instead of discarding it.
- For a game that is its own OpenID Provider over TLS, optionally runs
the client-driven PKCE flow end to end (`Char.Login.AuthCode`).
#### Motivation for adding to Mudlet
Modern games are moving to browser-based single sign-on; this lets
Mudlet players use those accounts directly, and reconnect without
re-entering anything — while classic character-name/password logins keep
working unchanged.
#### Other info (issues closed, discussion etc)
- Reworks the approach to resolve @vadi2's UX feedback
(https://github.com/Mudlet/Mudlet/pull/9373#issuecomment-4865669499):
there is **no client pop-up and no in-client chooser**. The game owns
the sign-in screen and offers the choice as text; Mudlet only automates
the mechanical hooks around it (autofill, open URL, save token, replay
token).
- Supersedes and closes #9373.
- Implements the revised v2 draft spec, inspired by #9354.
- Covered by new tests: `OAuthClientFlowTest` (OIDC discovery, PKCE,
loopback capture) and the `GMCPCharLoginTest` functional suite driving a
GMCP server stub through the full client flow.
- Try it out on StickMUD.
https://github.com/user-attachments/assets/566947f6-4f43-4bff-b98c-9328b7a40a2d
---------
Signed-off-by: Michael Conley <sousesider@gmail.com>
|