#414·ego-lite

[Bug]: Widevine CDM never loads on macOS — library validation rejects it, all DRM video stalls silently

Author: nbhaohaoCreated Sep 20, 2026Updated Sep 20, 2026

What happens

All Widevine-protected video fails to play in ego lite on macOS (arm64). The player loads the manifest, then silently stalls: no media segments are requested, no license request is made, video.readyState stays 0, and video.error stays null — so the page shows a black frame with no error message.

Reproduced on Udemy. Any Widevine (EME) site should be affected.

The exact same content plays fine in Safari on the same machine, same account, same network — Safari uses FairPlay rather than Widevine, so it never touches the CDM below. This rules out the account, the content and the network, and isolates the problem to ego lite's Widevine path.

Minimal reproduction

No login and no DRM site needed. Open any page in ego lite and run:

javascript
await navigator
  .requestMediaKeySystemAccess("com.widevine.alpha", [{
    initDataTypes: ["cenc"],
    videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.640028"' }],
  }])
  .then((access) => access.createMediaKeys());

Actual:

NotSupportedError: CreateCdmFunc not available.

Expected: resolves with a MediaKeys object.

Note that requestMediaKeySystemAccess() itself resolves successfully — it is answered from the component manifest without touching the CDM binary. The failure only surfaces at createMediaKeys(), when the library is actually loaded. This is why affected pages detect DRM as "supported" and then stall with no error.

Root cause

macOS library validation is rejecting the Widevine CDM. From the kernel log (log show --predicate 'eventMessage CONTAINS "libwidevinecdm"'), one entry per playback attempt:

AppleMobileFileIntegrity: Library Validation failed: Rejecting
'/Users/<user>/Library/Application Support/Citro Labs/ego lite/WidevineCdm/4.10.3050.0/_platform_specific/mac_arm64/libwidevinecdm.dylib'
(Team ID: EQHXZ8M8AV, platform: no) for process 'ego Helper' (Team ID: JGQLC6YQYJ, platform: no),
reason: mapping process and mapped file (non-platform) have different Team IDs

The CDM is signed by Google (EQHXZ8M8AV); the helper process is signed by Citro Labs (JGQLC6YQYJ). Loading it therefore requires the loading process to opt out of library validation.

ego Helper.app does the opposite — it explicitly opts in, and carries no entitlements at all:

$ codesign -dvvv "ego Helper.app"
CodeDirectory v=20500 flags=0x12a00(kill,restrict,library-validation,runtime)
TeamIdentifier=JGQLC6YQYJ

$ codesign -d --entitlements :- "ego Helper.app"
(none)

For comparison, five other Chromium/Electron apps on the same machine (Cursor, Obsidian, Claude, Postman, Orca) all sign their helpers flags=0x10000(runtime) — none of them set the library-validation flag.

No binary anywhere in ego lite.app carries com.apple.security.cs.disable-library-validation.

Suggested fix

Upstream Chromium handles this with a dedicated helper variant for exactly this reason: Google Chrome Helper (Plugin).app, built with helper-plugin-entitlements.plist, which contains com.apple.security.cs.disable-library-validation specifically so the Google-signed Widevine CDM can be loaded by a differently-signed browser.

ego lite ships no such variant:

$ ls Contents/Frameworks/ego\ Framework.framework/Versions/0.5.0.32/Helpers/ | grep Helper
ego Helper (Alerts).app
ego Helper (GPU).app
ego Helper (Node).app
ego Helper (Renderer).app
ego Helper.app

So the CDM utility process falls back to the generic ego Helper.app, where library validation is enforced and the load is denied.

Adding the (Plugin) helper variant with the disable-library-validation entitlement should restore Widevine playback. The CDM itself is fine — it is present, up to date (chrome://components reports 4.10.3050.0, "Up-to-date"), correctly signed (codesign --verify passes), and byte-identical to a copy that works in another Chromium app on the same machine.

Environment

  • ego lite 0.5.0.32 (arm64)
  • macOS Darwin 25.6.0, Apple Silicon
  • Widevine CDM component 4.10.3050.0
  • Chrome/152.0.0.0 (per UA string)