mirror of
https://github.com/LowganDev/PlayfinPS4.git
synced 2026-10-18 01:01:48 +02:00
5.9 KiB
5.9 KiB
Security notes
Network
- HTTPS certificates are verified against the Mozilla CA list shipped in
resources/certs/cacert.pem(the console's own list can be outdated). - Self-signed servers: trust on first use. The app shows the SHA-256 fingerprint of the server's public key; once
accepted, that exact key is pinned (
servers.json) and any other key is refused, even one signed by a known CA. A changed key is refused (TLS error telling the user to add the server again); trusting the new key takes that explicit re-add. Saved tokens are only sent to addresses the server was already known by: a new address (for example a discovery reply carrying a known server id) needs a sign-in there first. When an address has several candidates (https/http, default ports), an untrusted certificate is offered only if no candidate answers as Jellyfin. - Redirects never go from https to http; API (JSON) replies are limited to 8 MiB, files (
Client::fetch) to 64 MiB; requests time out. - Discovery keeps at most 32 servers and ignores replies with an id or name over 128 bytes or an address over 512 bytes.
- The access token travels only in the
Authorizationheader, never in URLs (images included), andClient::fetchrefuses to send it to another host.
Storage
servers.json(data folder, mode 0600, atomic writes) holds server addresses, pins, user names and access tokens. Passwords are never stored.- The PS4 has no secure storage: anyone with file access to the console can read the tokens. If a console is lost, revoke its session in the Jellyfin dashboard (Devices).
- Without a data folder, or when
servers.jsoncannot be read, the app runs without saving and never overwrites the file. - The app writes only inside its data folder (
/data/Playfinon PS4); every path goes throughcore::dataPath().
Logs
- Every log line is redacted (
core::redact): API keys, tokens,Authorizationheaders, password fields and the Quick Connect secret are replaced by***. Request bodies are never logged.
Testing
- Server replies, discovery packets, addresses and log redaction are fuzzed (
linux-fuzzpreset).
Review
A review of the whole code. Threats considered: someone on the network (Wi-Fi, LAN), a malicious or compromised server, a malicious media file served by a trusted server (downloaded content), other homebrew on the console.
| Area | Finding | Action |
|---|---|---|
| Pictures from the server | NanoVG's bundled stb_image was v2.10 (2016). Fuzzing decodeImage (fuzz_image) found an out-of-bounds write in its JPEG Huffman table code within minutes: a server could crash the app, or worse, with a crafted picture. Every decoder of stb_image was compiled in (PSD, GIF, HDR…). |
stb_image 2.30 (upstream 2c980bb), only the JPEG and PNG decoders (STBI_ONLY_JPEG, STBI_ONLY_PNG), STBI_MAX_DIMENSIONS 4096 on top of the existing header check (4096 px a side, 8 Mpx: a progressive JPEG needs about 13 bytes per pixel while it decodes, two decodes at once on the PS4). The crashing file is a regression test (images_test, ASan) and a fuzz seed. 5 minutes of fuzzing without a finding after the change. |
| Subtitles (libass) | The PS4 image's libass 0.14.0 has CVE-2020-24994 and CVE-2020-26682 (crafted ASS subtitles overflowing the outline code). | libass 0.17.3 built by scripts/ps4/libass (with HarfBuzz 11.2.1, scripts/ps4/harfbuzz, required since libass 0.15). |
| Fonts (FreeType) | The image's FreeType 2.10.1 has CVE-2020-15999 (heap overflow on PNG glyphs, exploited in the wild in 2020). Fonts attached to media files reached FreeType through libass. | mpv runs with embeddedfonts=no (only Playfin's fonts reach FreeType), and FreeType 2.13.3 is built by scripts/ps4/freetype without bzip2, PNG glyphs, brotli or HarfBuzz (libpng 1.6.37 is no longer linked). |
| FFmpeg's bzip2 | FFmpeg was built with bzlib against the image's bzip2 1.0.6 (CVE-2016-3189, CVE-2019-12900), reachable through bzip2-compressed Matroska tracks. | FFmpeg built with --disable-bzlib; bzip2 is no longer linked. |
| Player | mpv could read configuration and scripts (already off), and a media file could make it open other files (mov references, playlists). | player::hardeningOptions() (tested): config=no, load-scripts=no, ytdl=no, input-default-bindings=no, embeddedfonts=no, access-references=no, load-unsafe-playlists=no. FFmpeg keeps only the decoders, demuxers and protocols Jellyfin's streams need. |
| TLS and the token | Verified against the shipped Mozilla list; pinned keys for self-signed servers; the token only in the Authorization header, sent to the server's own origin only (images, streams, transcoding URLs: api_key removed, other hosts refused). FFmpeg cannot check a pin: for a pinned self-signed server mpv streams with tls-verify=no (docs/ps4-notes.md). Plain HTTP servers on the LAN send the token in clear, as every Jellyfin client does. |
No change (documented above). |
| Parsing | JSON replies, discovery packets, URLs, settings, timers: bounded sizes, fuzzed (fuzz_models, fuzz_discovery, fuzz_url). |
parseTimers and parseUtc added to fuzz_models. |
| Files | Writes only in the data folder (core::dataPath), atomic, 0600 for servers.json and settings.json; caches bounded. |
No change. |
| Logs | Redacted (core::redact); request bodies never logged; the access token test of ui_shell. |
No change. |
| Other dependencies | curl 8.22.0, Mbed TLS 3.6.7, FFmpeg 7.1.5, dav1d 1.5.4, zlib 1.3.1 are current. mpv 0.36.0 (2023), SDL2 2.0.18 (PacBrew PS4 port), FriBidi 1.0.4 and libsamplerate 0.1.9 are older: SDL2's published flaws are in loaders Playfin does not use (BMP, WAV); FriBidi's (CVE-2022-25308/25309/25310) are in its command-line tool and in functions libass does not call. | Recorded; to revisit when updating mpv (a newer mpv needs the PS4 patch ported). |
The PS4 dependency packages are built from scripts/ps4 by scripts/ps4/build-deps.sh and published on the
deps release of the repository (docs/release.md).