MPV.Rocks Installer — Combined Cross-Referenced Review (glm-5.3)

Date: 2026-08-31 · Baseline: bdfb31b95030c2d992e5cfc4cb0ba5bada368d1b (master)
Sources cross-referenced: Review A (glm-5.3) = CODEBASE_REVIEW_2026-08-31_glm-5.3.md (154 findings) · Review B (prior) = CODEBASE_REVIEW_2026-08-31.md (50 findings)
This report cross-references every finding, independently verifies all single-sourced claims, resolves severity disagreements, and merges the remediation roadmaps. Markdown companion: CODEBASE_REVIEW_COMBINED_2026-08-31-glm-5.3.md
41
Corroborated clusters
9
Unique to prior — all re-verified
~104
Unique to glm-5.3
0
Refuted claims
7
Severity disagreements resolved

Combined severity totals — deduplicated across both reviews (204 raw findings → 153 distinct issues), harmonized per §5

1
Critical
31
High
68
Medium
48
Low
5
Info
153
Total distinct issues

1. Cross-reference outcome

The two reviews agree on every mutually-inspected high-risk area and disagree on almost nothing factually — where they overlap, file/line references match within a few lines. The prior review's dynamic tooling (Staticcheck, race, shuffle, live Chromium, coverage) and the glm-5.3 audit's broader static depth are complementary: Review B caught 9 issues glm-5.3 missed (notably a privilege-escalation path and a config-tree divergence), while Review A caught ~104 issues Review B missed (notably the updater's exec-before-hash ordering, crash-consistency defects, and large TUI/frontend correctness surfaces).

Combined dynamic validation (union of both reviews + this session)
CheckResultSource
go vet ./...PassB; re-run this session (A)
go test ./...Pass, all packagesA (this session) + B
go test -race -count=1 ./...PassB
go test -shuffle=on -count=3 ./...PassB
gofmt / tidy -diff / mod verify / git diff --checkPassB
govulncheck@v1.7.0 (Go 1.27)0 vulnerabilitiesB
Staticcheck 0.8.1 (SA*)13 diagnostics; 4 production correctness findingsB
npm test (157 assertions, shuffled too)PassB
npm audit --audit-level=moderate0 vulnerabilitiesB
Alpine/htmx vendor freshnessPass, byte-for-byteB
Six release cross-buildsPassB
Local Web route/API/auth smoke testPass (cookie auth, hostile Host/Origin, graceful shutdown)B
Live Chromium jobs-modal focus reproductionReproducedB
Coverage (one repo-wide run)43.7% overall; installer 84.1%, platform 92.3%, version 72.9%, config 70.3%, web 28.5%, TUI 26.0%, cmd 11.9%B
Source re-verification of all 9 Review-B-unique claimsAll confirmedThis session

2. Tier A — Corroborated findings (41 clusters, independently found by both reviews)

Highest-confidence findings of the audit. Severity harmonized (§5).

A.1 Corroborated Critical/High (13 clusters)

#FindingA (glm-5.3)B (prior)Verification
1CRITICALRelaunched self-updated TUI renders into helper.log while consuming terminal input; health acknowledged before any real initialization, so the broken relaunch can be committed as "healthy"C-1 + H-3H-15Source-verified by both; B notes ack placement in main.go
2HIGHWindows uninstall recursively deletes the install directory with no ownership proof; per-entry errors are warnings; success returned regardlessH-6H-02A lead verified windows.go:103-157
3HIGHTUI update/uninstall drops AppID/InstallPath; operations run against the global installer destination — selecting install B can update/delete install AH-14H-03Both traced models_types.go / models_update.go
4HIGHJob cancellation archives/removes the job before the worker stops; a conflicting destructive job is accepted while side effects continueH-11H-05Both traced jobs.go:482-543
5HIGHJob conflict detection protects method IDs, not shared resources; different methods (or direct config APIs) can concurrently mutate the same config/UI treeI-M5 (Med→High)H-06Both traced jobs.go:256-279
6HIGHPhysical success reported when authoritative persistence fails (untracked installs, tracked uninstalls, stale adoption/UI metadata)T-M2 (Med→High)H-07Both traced install/adopt workers
7HIGHConfig setters mutate in-memory state and return errors without rollback; failed mutations later persisted by unrelated successful savesP-M2 (Med→High)H-08Both enumerated setter families
8HIGHConfig restore renames the live file aside before validating/staging the replacement; no rollback; date-only backup names collide same-dayH-20H-10Both traced installer.go / common.go
9HIGHPackage-version "10 s timeout" ineffective: unlabeled break exits only the select; unkillable probes; run at startup and under the cache write lockH-10H-11A lead verified line 313; Staticcheck SA4011 flags the same line (B)
10HIGHIINA install discards hdiutil attach output, assumes /Volumes/IINA; volume collision copies an unverified bundle; detaches the wrong pathH-9H-12Both traced macos.go
11HIGHUnauthenticated upstream "latest" artifacts hashed and signed into MPV.Rocks trust (no upstream signature/allowlist check)U-M12 (Med→High)H-14Both traced generate-info
12HIGHFFmpeg replacement: deferred deletion of ffmpeg.old runs even when the rollback rename failed — destroys the only known-good binaryH-7H-16Both traced installer.go:525-614
13HIGHTUI language apply renames the entire mpv.conf away for a single-field write; editor writes fresh defaults (all user settings vanish); failed rename ignoredH-16H-17Both traced language_preferences.go / editor.go

A.2 Corroborated Medium (23 clusters)

#FindingAB
14uOSC/ZIP extraction runs external Expand-Archive -Force/unzip -o directly over live config; rollback allowlist covers only known UI pathsI-M6M-01
15Crash before the first updater journal write permanently blocks future updates (orphan dir; recovery stops at first bad dir)U-M2M-03
16Windows discovery executes every discovered mpv.exe --version from user-writable/PATH/registry locations before adoption, unboundedI-M1M-04
17Multi-field config/language API writes validated together, persisted field-by-field; partial apply on mid-failure (batch writer exists, unused)W-M5M-05
18Job-history serialization per-Store instance; TUI creates fresh stores; fixed .tmp name; cross-process record lossP-M7/S-M8/T-M10M-06
19Persistent SSE handlers defeat graceful shutdown: 2 s timeout → fatal → exit 1 with a connected browserS-M1M-07
20SSE terminal-event delivery/reconnect gaps: narrow concurrent-sender drop window; reconnect snapshots only active jobs; client never reconcilesF-M2 + LowM-08
21TUI Ctrl+C quits without cancelling/joining backend work (context.Background workers; children outlive the TUI)H-18M-09
22UI migration resolution spans two stores with check-then-act, no CAS; file changed while resolution says KeepL-2 (Low→Med)M-10
23Jobs modal opens focus controller while still hidden; initial focus lands on inert bodyF-M6M-11 (reproduced in live Chromium)
24Windows resources: only amd64 .syso, hardcoded 1.0.0.0/Win7; generator failures suppressed; arm64 has noneB-M2 + LowM-12
25Manager-data reset ignores backup failure, overwrites a fixed .backup, logs success; TUI claims "backup saved"T-M13M-13
26Backup validation misses intermediate symlinks; restore/delete can escape the backup dirW-M2/P-M1M-14
27File/config locks process-local while Web/TUI/CLI share the same files (snapshot Write parses before locking)S-M6/S-M7M-15
28Privileged release jobs run mutable container tags (alpine:latest, release-cli:latest)B-M6M-16
29TUI PATH add/remove: non-idempotent aliases, failures reset to nil, removal never removes aliases, Windows brokenT-M9M-18
30Release-generator artifact downloads unbounded in time and sizeU-M9/B-M4M-19
31Signed manager manifest computed from re-downloaded registry bytes, not the pipeline's build artifactsH-21 (High; B Med)M-20
32BLAKE3SUMS.txt emits blake3: prefix — incompatible with documented b3sum -c; never exercised by CIU-M11/B-M8M-21
33Stored-password Web installs dispatch the privileged request twice (ensurePassword invokes callback and returns true)F-M1M-22
34Config Apply baseline rebuilt from current controls, not the submitted payload; concurrent edits silently marked savedF-M3M-23
35UI-option saves and regional-language requests allow stale responses to overwrite newer intentF-M4 + F-M5M-24
36CLI --path ignored by ModernZ/uOSC/FFmpeg dispatch but recorded as InstalledApp.InstallPathS-M9M-25

A.3 Corroborated Low (5 clusters)

#FindingAB
37No CSP on the privileged loopback UIFrontend LowL-02
38Public parsed script-options Write can overwrite fresher edits (no revision check)Support LowL-05
39Reset text claims language preferences cleared; they live in mpv.confT-M13 (partial)L-06
40Staticcheck-exposed TUI defects (SA4005 value receiver, SA4014 duplicate branches, SA9003 empty branches)TUI LowsL-07
41Docs claim macOS universal output that CI contradicts; release metadata/native gates unenforcedB-Low + U-Low + H-23 contextL-08 + coverage gaps

3. Tier B — Unique to the prior review (9 findings — all re-verified this session)

VERIFIEDEvery finding only Review B reported was independently confirmed against source during this cross-reference session. None is refuted. Net effect: the prior review contributed 4 new High findings (B-1 privilege escalation, B-2 config-tree divergence, B-3 defaults-on-read-failure, B-4 signing-key separation) that materially expand the risk picture beyond the glm-5.3 audit.

HIGHB-1 — Windows uninstall elevates a mutable install-tree batch file

pkg/installer/windows.go:160-212 · common_handler.go:165-184 · models_messages.go:419-423 (B: H-01)

mpv-unregister.bat is copied from the (possibly adopted, user-writable) MPV tree and executed via Start-Process -Verb RunAs with no digest/ownership/ACL check before UAC. An unprivileged process can replace the .bat and wait for the user to approve the expected prompt → admin code execution.

This session: confirmed — copy from install tree, fallback to the original path, elevated Start-Process, zero verification.

HIGHB-2 — Custom installs and settings APIs resolve different portable_config trees

pkg/constants/paths.go:52-72 · pkg/web/api_settings.go:479-518 (B: H-04)

Installer writes <custom>\portable_config, but config/hotkeys/ModernZ/uOSC/migration/backup resolvers use %APPDATA%\mpv or legacy home; the common resolver never consults the configured custom path (and caches with sync.Once). UI reports success against a tree MPV never reads.

This session: confirmed — getWindowsMPVBaseDir checks only APPDATA/home existence via windowsPathOnce.

HIGHB-3 — Config read failures treated as "missing file" and replaced with defaults

pkg/config/config.go:85-149 (B: H-09)

Permission errors, transient I/O failures, and unavailable mounts all fall through to default configuration and are saved over the existing file. The parse-error log prints the shadowed outer err (always <nil>).

This session: confirmed — any ReadFile error reaches "Start fresh defaults" + saveLocked(); inner err shadows the read error used in the log.

HIGHB-4 — Tagged generator code receives the long-lived release signing key

.gitlab-ci.yml:495-496 · cmd/generate-info/main.go:517-527 (B: H-13)

CI builds cmd/generate-info from the tag, injects MANIFEST_SIGNING_KEY, and executes that artifact. A malicious or compromised tagged generator can export the private key and forge future manifests; protected-tag rules do not separate signer trust from the code being authorized.

This session: confirmed — the generator job requires MANIFEST_SIGNING_KEY_ID/MANIFEST_SIGNING_KEY.

#FindingBThis session's verification
B-5MEDMulti-target self-update locks only the primary executable; concurrent primary/secondary updates can both mutate the same secondaryM-02CONFIRMEDtransaction.go:205-210: single tryAcquireUpdateLock(updateLockPath(primaryPath))
B-6MEDReduced-motion preferences don't cover dialog animations (generic/job/password/UI-select modals)M-17CONFIRMEDstyle.css:430-455 covers toast/badge/progress/priority-list only
B-7LOWManifest-status network exceptions leave install controls enabled (catch only logs)L-01CONFIRMEDmanifest-status.js:34-48: catch does console.error only
B-8LOWLocal make release can package stale frontend assets (no frontend deps/freshness/tests in the chain)L-03CONFIRMEDMakefile:227 chain; also corroborates A's B-M3 (release-build omits trust check)
B-9LOWDuplicate hotkey lines only partially edited (first-match Set/Remove)L-04Consistent with the first-match parser traced by A's hotkeys review; not line-by-line re-verified

4. Tier C — Unique to the glm-5.3 review (~104 findings)

Single-sourced but lead-verified during the original audit. Grouped summary (full detail in the glm-5.3 report and .opencode/reviews/):

Updater / release stack (12)
  • Exec-before-BLAKE3-recheck TOCTOU at target-adjacent staging (H-1)
  • Apply/rollback crash windows with no launchable primary executable (H-2)
  • Missing backups treated as successful rollback (H-4)
  • v1.1/v1.2 legacy bootstrap unauthenticated (H-5)
  • No target-directory durability ordering with the journal (U-M1)
  • Forgeable PrepareSelfUpdateFromCheck DTO (U-M3)
  • No anti-replay/revocation/threshold on signed metadata (U-M4, U-M5)
  • Secondary-path identity never proven before replacement (U-M6)
  • Detached helper failures invisible to initiating UX (U-M7)
  • Kill-without-wait rollback race on Windows (U-M8)
  • Qualifier --qualifier-driver uncontained destructive mode (U-M10)
  • Release tag grammar validated only after publication begins (H-22/B-M7)
Installer / TUI / Web / core / frontend / main / CI (headline items)
  • Installer: config reset fail-open on preservation/backup failure (H-8); MPC-QT Start-Process without -Wait (I-M3); detection collapses uncertainty into "not installed" (I-M2); runtime file transactions not crash-durable (I-M7)
  • TUI: Escape abandons workers, Abort unreachable (H-12); nondeterministic stream completion — stuck "installing" or dropped output (H-13); "Change UI" full-reinstall + duplicate records (H-15); Enter-while-filtering triggers destructive actions (H-17); interactive sudo fights Bubble Tea for the raw terminal (H-19); stale "updates" menu ID (T-M1); progress bar 0–100 vs 0–1 unit bug (T-M5); quadratic output rendering (T-M7); Unicode backspace byte-slicing (T-M14); terminal control-sequence injection (T-M15); hardcoded version overlay (T-M11); ~33 s non-offline-first startup (T-M12)
  • Web: cached sudo timestamp accepts any password — sudo -S -v without -k (W-M1); locale cache data race (W-M4); ui_type unvalidated (Low); downgrades labeled updates (Low)
  • Core: quote-unaware # parsing in mpv.conf/input.conf/script-opts — three independent implementations (P-M3, P-M8, S-M4); Linux GPU model truncation and hybrid-order dependence (P-M4); macOS AV1 over-reporting incl. M2 (P-M5); arm64 labeled x86-64-v2 (P-M6); locale dataset/selection disagreements (P-M9); BOM/CRLF round-trip corruption (S-M5)
  • Frontend: SSE reconnect never reconciles (F-M2, corroborated); mobile drawer not focus-contained (Low); formatKeys template.HTML trust boundary (Low)
  • Main: subcommand/flag misrouting (--verbose cli starts Web) (S-M2); --verbose/--debug no-op console logging (S-M3); symlink-replacing atomic writes (S-M6); browser-launch/bind race (S-M10); os.Exit cleanup bypass; zombie browser helper
  • Build/CI: archives omit LICENSE/notices (B-M1); coverage regex not aggregate; make lint unpinned; browser E2E absence (B-M5)

5. Severity disagreements (resolved)

TopicA (glm-5.3)B (prior)Resolution
Helper-log relaunch + early health ackCRITICALC-1 + H-3HIGHH-15Critical. Both agree on facts. No supported recovery after commit, terminal silently captured, shipped qualification cannot detect it. Not attacker-triggerable RCE, but by impact-and-permanence the single worst defect.
Manifest signs re-downloaded registry bytesHIGHH-21MEDM-20High. GitLab permits duplicate generic-package files by default; the signature is the root of trust and must bind to pipeline-produced bytes. B's own remediation implies the same.
Job conflict detection scopeMEDI-M5HIGHH-06High. Overlapping config/UI mutations can roll back committed work — authoritative-state failure.
Persistence-failure false successMEDT-M2HIGHH-07High. Tasks UI as untrustworthy state is a core-flow failure.
Config setter rollbackMEDP-M2HIGHH-08High. Failed mutations later persisted by unrelated saves.
UI migration CASLOWL-2MEDM-10Medium. Two-store check-then-act verified this session.
TUI Ctrl+CHIGHH-18MEDM-09High. Combined with Escape abandonment and shutdown-orphaned jobs, one systemic lifecycle failure (Theme 3).

6. Combined cross-cutting themes

  1. Update/relaunch lifecycle unsafe end-to-end — helper.log relaunch, early health ack, exec-before-hash, no-launchable-exe windows, dishonest rollback, secondary-lock gap, unauthenticated legacy bootstrap, signing-key separation (B-4), registry-bytes provenance, upstream auto-promotion.
  2. Destructive operations without ownership or transaction — uninstall sweep + elevated mutable .bat (B-1), wrong-target TUI operations, config-tree divergence (B-2), fail-open config reset/restore, FFmpeg backup deletion, language-apply rename, defaults-on-read-failure (B-3), date-colliding backups.
  3. Worker lifecycle not owned by cancellors — Web cancel-then-accept, TUI Escape/Ctrl+C, shutdown abandoning jobs/SSE/children.
  4. Authoritative state can lie — persistence-failure false success, setter non-rollback, partial multi-field writes, detection collapsing uncertainty, CLI --path recording fiction.
  5. Coordination is process-local — method-ID job slots, per-Store history, path locks, migration CAS.
  6. Release trust boundary too broad — tag-built generator with the signing key, mutable CI images, tag grammar after publication, unenforced metadata/native gates, checksum-file incompatibility.
  7. Quote-unaware parsers (×3) — mpv.conf, input.conf, script-opts all split on # without quote tracking.

7. Unified remediation roadmap (merged)

P0 — release blockers

  1. Terminal-preserving relaunch + post-first-render health acknowledgement + PTY qualification (C-1/H-15, H-3).
  2. Windows destructive/privileged wrong-target fixes: ownership manifests (H-02/H-6), authenticated fixed helper instead of elevated mutable .bat (H-01/B-1), app-identity-carrying TUI operations (H-03/H-14), one installed-app-aware config resolver (H-04/B-2).
  3. Updater integrity: hash-before-exec, platform-atomic never-unlinked replacement, honest rollback on missing backups, per-target locks (H-1/H-2/H-4, M-02/B-5).
  4. Fail-closed transactional config reset/restore with unique fsynced backups (H-8, H-10/H-20, H-16/H-17), defaults-only-on-os.IsNotExist (H-09/B-3).
  5. FFmpeg staged replacement (H-16/H-7); IINA mount-bound copy (H-12/H-9).

P1 — authoritative state and lifecycle

  1. Worker-acknowledged cancellation; root lifecycle contexts; SSE-aware graceful shutdown (H-05/H-11, M-09/H-18, M-07/S-M1).
  2. Resource-keyed operation leases covering config/UI trees and direct APIs (H-06/I-M5).
  3. Persistence as part of the terminal result; setter rollback via one primitive (H-07/T-M2, H-08/P-M2).
  4. Package-probe timeout fix + blocked-probe test (H-11/H-10, SA4011).
  5. Release trust boundary: sign pipeline-local artifacts, isolated minimal signer/KMS separate from tagged code (M-20/H-21, H-13/B-4), pinned upstream digests + approval boundary (H-14/U-M12), protected semantic tags + duplicate preflight + serialized publication, pinned image digests.
  6. TUI stream protocol, filter-state guards, interactive-sudo suspension (H-13, H-17, H-19).

P2 — reliability, portability, compliance

  1. Native extraction policy for ZIP/tar; crash-durable installer transactions (M-01/I-M6, I-M7).
  2. Cross-process locks for history/config; migration CAS (M-06, M-10, M-15).
  3. Frontend contracts: ensurePassword single-owner, SSE reconnect reconciliation, latest-intent saves, $nextTick modal focus, reduced-motion dialogs (M-22–M-24, M-11, M-17).
  4. b3sum -c-compatible checksums + tests; license notices in archives; Windows resources for both arches; tag grammar before publication; generator download bounds (M-21, M-19, M-12).
  5. Discovery without executing untrusted binaries (M-04/I-M1); MPC-QT wait/verify (I-M3).

P3 — quality and cleanup

  1. Browser E2E suite in CI (both reviews' top test gap); fault-injection tests at commit boundaries; language-workflow tests; coverage floors for Web (28.5%) / TUI (26.0%) / cmd (11.9%).
  2. All Low/Info items; docs reconciliation; Staticcheck SA* in CI.

8. Combined strengths (union)

9. Review limitations