#### Brief overview of PR changes/additions
- Reject MSP/GMCP media file names containing `..` that resolve outside
the profile's media directory (relative sub-directories and wildcards
still work).
- Guard `TEntityResolver::resolveCode()` against the empty value from a
malformed numeric entity like `&#;`, which previously called
`QString::front()` on an empty string (undefined behaviour).
- Add a `TEntityResolver` regression test for the malformed-entity case.
#### Motivation for adding to Mudlet
A connected game server could use a crafted MSP `!!SOUND`/`!!MUSIC` or
GMCP `Client.Media` file name to download and write attacker-controlled
content to an arbitrary path (e.g. an autostart entry), or read/play an
arbitrary local file — with no user interaction, since both protocols
are enabled by default.
#### Other info (issues closed, discussion etc)
Security hardening of the server-facing media path. `isFileRelative()`
only rejected absolute paths, so a relative `..` traversal passed
validation before being concatenated onto the media directory.
**Test case:** Connect a profile to a server that sends
`!!SOUND(../../evil.wav U=http://example/evil.wav)` — it is now rejected
with a `WARNING - rejected a media file name that escapes the profile
media directory` log line, while a normal `!!SOUND(hit.wav U=...)` still
downloads and plays.
---
_Generated by [Claude
Code](https://claude.ai/code/session_011XUZefuDuy8F1M4bHq5jMZ)_
---------
Signed-off-by: Vadim Peretokin <vperetokin@hey.com>
Co-authored-by: Claude <noreply@anthropic.com>