FARPSEC
Intelligence

CVE-2026-69446 — Microsoft Edge and To Do macOS DYLD Code Injection to Credential Theft

Two Microsoft macOS apps shipped without library-validation, allowing DYLD_INSERT_LIBRARIES injection. EdgeUpdater escalates to root through an unsanitized install script. To Do goes deeper — the injected code inherits sandbox entitlements and can call the full OneAuth/MSAL framework to steal OAuth tokens across every Microsoft app on the Mac.

CVE: CVE-2026-69446
MSRC Cases: 114396 (EdgeUpdater), 122314 (Microsoft To Do)
Severity: Elevation of Privilege
Affected: Microsoft Edge for macOS (EdgeUpdater), Microsoft To Do for macOS
Credit: Maliq Barnard


Two products, one vulnerability class

Microsoft ships multiple macOS binaries without the code signing flags that prevent dylib injection. I found it in two of them — EdgeUpdater and Microsoft To Do — each with a different exploitation depth. Both are grouped under CVE-2026-69446.

The root cause is the same: missing CS_RESTRICT and library-validation in production binaries. On macOS, without CS_RESTRICT, dyld does not strip DYLD_INSERT_LIBRARIES from the environment. Without library-validation, dylibs signed by any identity — including ad-hoc — are loaded. Set one environment variable, inject arbitrary code.

This is the same vulnerability class as CVE-2024-42220 through CVE-2024-42227, where Cisco Talos received eight separate CVEs for the same issue across eight different Microsoft macOS apps. I found two more products still affected.

Part 1: EdgeUpdater — root escalation through install.sh

Every binary in Edge for macOS ships with hardened code signing except EdgeUpdater. Here is what the flags look like across Edge 147.0.3912.72:

BinaryFlagsCS_RESTRICTLibrary ValidationCS_KILLSDK
Microsoft Edge0x12a00YesYesYes26.2.0
Microsoft Edge Helper0x12a00YesYesYes26.2.0
Edge Helper (GPU)0x10a00YesNoYes26.2.0
Edge Helper (Renderer)0x10a00YesNoYes26.2.0
EdgeUpdater0x10000NoNoNo15.2.0
updater_oneds.so0x10000NoNoNo15.2.0

EdgeUpdater is built against macOS 12 SDK (Runtime Version 15.2.0) while everything else targets macOS 26 SDK. A component compiled years ago and never brought forward.

The escalation to root goes through install.sh, shipped at Microsoft Edge Framework.framework/Resources/install.sh. This script runs with bash -p to preserve EUID=0 and directly executes EdgeUpdater with --install --system at line 136. It sanitizes $PATH but does not sanitize DYLD_* environment variables. If DYLD_INSERT_LIBRARIES is set when the script runs as root, the injected dylib executes as root inside EdgeUpdater.

The PoC injected a dylib into EdgeUpdater and accessed 208 keychain items, including Safari Forms AutoFill Encryption Key, ProtectedCloudStorage entries, and Apple assistant certificates. Both the parent process and its spawned child were injected. EdgeUpdater also disables App Transport Security entirely (NSAllowsArbitraryLoads = true), giving the injected code unrestricted network access.

Part 2: Microsoft To Do — OneAuth token theft

Microsoft To Do (v2.169, com.microsoft.to-do-mac) ships with com.apple.security.cs.disable-library-validation=true in its production entitlements. Same injection vector, but the exploitation goes much deeper because To Do loads the full OneAuth/MSAL authentication framework.

The chain, all steps live-verified on macOS 26.6:

  1. Code injection — unsigned dylib loaded via DYLD_INSERT_LIBRARIES, constructor runs inside the App Sandbox (PID 5823).
  1. Keychain theft — 225 keychain items enumerated, including Chrome Safe Storage key, Safari Forms AutoFill Encryption Key, ChatGPT private access tokens, Cursor/Codex safe storage keys, and AirPlay server identity.
  1. Cross-app keychain access — all Microsoft shared keychain groups accessible: UBF8T346G9.com.microsoft.identity.universalstorage, com.microsoft.adalcache, com.microsoft.edgemac.devicetrust, com.microsoft.edgemac.webauthn.
  1. OneAuth OAuth redirect bypass — called +[MSAIMSIDRedirectUriVerifier msidRedirectUriWithCustomUri:clientId:bypassRedirectValidation:error:] with bypassRedirectValidation:YES. Returned a valid MSAIMSIDRedirectUri object. This enables redirecting OAuth token flows to attacker-controlled endpoints.
  1. MSAL token cache API — instantiated MSAIMSIDDefaultTokenCacheAccessor with MSAIMSIDMacKeychainTokenCache as the data source. Called allTokensWithContext:error: — succeeded. On a machine with a signed-in Microsoft account, this returns access tokens, refresh tokens, ID tokens, and Primary Refresh Tokens for all Microsoft services.
  1. 435 MSAL classes loaded — the full OneAuth framework is callable from injected code, including MSAIMSIDAccessToken, MSAIMSIDRefreshToken, MSAIMSIDIdToken, MSAIMSIDPrimaryRefreshToken, and MSAIMSIDFamilyRefreshToken. Token classes expose .accessToken, .refreshToken, .rawIdToken, and .sessionKey properties.

The key difference from EdgeUpdater: To Do runs inside the App Sandbox, so the injected code inherits all of the app's sandbox entitlements and keychain access groups — including the identity groups shared across every Microsoft app on the Mac. That makes this a credential theft chain, not just code execution.

The fix

Microsoft confirmed the EdgeUpdater behavior on June 11, 2026, and the To Do chain on July 15, 2026. CVE-2026-69446 was published August 11, 2026. The fix adds the missing code signing flags and removes the disable-library-validation entitlement from production builds.

Timeline

DateEvent
April 24, 2026EdgeUpdater submitted to MSRC (VULN-184326)
April 24, 2026Case 114396 opened
June 11, 2026Microsoft confirmed EdgeUpdater behavior
June 13, 2026To Do chain submitted to MSRC (VULN-195217)
June 15, 2026Case 122314 opened
July 15, 2026Microsoft confirmed To Do chain
August 11, 2026CVE-2026-69446 published

Notes

The thing that connects these two findings is a single check: run codesign -d --verbose on every binary in a bundle and diff the flags. EdgeUpdater stood out because it was the only Edge binary without CS_RESTRICT. To Do stood out because disable-library-validation is an explicit opt-out that shows up in the entitlements XML.

Once you are inside To Do, the 435-class MSAL framework turns a code injection into a credential theft operation. The bypassRedirectValidation:YES parameter is the kind of thing that exists for internal testing and should never be callable from production code. It was.