A bouncer checks your ID, then turns his back while you swap the badge and walk in as root
The vulnerability is a time-of-check to time-of-use race in the privileged helper installed by TeamViewer Full Client and Host on macOS prior to version 15.83. During package verification before installation, the helper checks a file, but an attacker with a local low-privileged account can swap a symlink between the check and the actual install. That lets the helper approve a legitimate package, then install a different, malicious .pkg as root. The result is local privilege escalation to root on the affected Mac.
Vendor severity of 7.8 (HIGH) is theoretically defensible for a local privilege escalation with root impact, but it doesn't match the real-world exposure. The attack requires an existing low-privileged local account, a race condition with no public exploit, and a macOS host running TeamViewer. In enterprise patch programs, this behaves more like a medium-severity local EoP bug: patch within a normal update cycle, but it's not network-reachable and there is no evidence of active exploitation.
4 steps from start to impact.
Obtain low-privileged local access
- Standard user account on affected macOS host
- TeamViewer Full Client or Host <15.83 installed
- Local account already means the attacker is past the perimeter
- macOS user sessions often require credentials or physical access
- Not applicable to fully patched hosts
Trigger TeamViewer's privileged helper
- Ability to invoke the helper or wait for an update/install event
- Write access to a directory used by the helper's package path
- TeamViewer update behavior may be infrequent or require specific user/root context
- Modern macOS may enforce path protections on some directories
Swap the verified package with a malicious one via symlink
- Attacker can create symlinks in the relevant directory
- Timing within the check-to-use window
- No public PoC weaponizes this yet
- Race may require repeated tries; macOS file-system timing varies
- SIP/TCC may limit some post-exploitation paths if attacker tries to tamper with system binaries
Run arbitrary code as root
- Malicious package can install without additional user approval
- Matching code signing requirements if any
- macOS TCC can restrict some root-level actions like accessing protected user data or camera/mic without user consent
- MDM and EDR may quarantine unsigned packages depending on policy
- Firewall/network segmentation won't help because the attack is a local file-system race, not network.
- Gatekeeper/XProtect may not catch a malicious package if it is signed ad hoc or the helper bypasses verification; do not rely on it.
- macOS SIP does not stop this because SIP protects system files but the privileged helper has legitimate root privileges to install packages; the flaw is in the helper's logic.
The supporting signals.
| In-the-wild status | No known active exploitation; not in CISA KEV |
|---|---|
| PoC availability | No public exploit or PoC identified (checked VulDB, Rapid7, GitHub/CVE-2026-92374, pocindex.io) |
| EPSS | 0.00092 (0.09%) as of 2026-11-01 |
| KEV | Not listed |
| CVSS | 7.8 (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H); local vector, root-level confidentiality/integrity/availability impact |
| Affected versions | TeamViewer Full Client and Host for macOS prior to 15.83 |
| Fixed version | 15.83 |
| Disclosure date | 2026-10-27 |
| Reporter/org | TeamViewer security bulletin TV-2026-1011 |
| Exposure | No scanning data from GreyNoise/Shodan for a local macOS helper; exposure is endpoint-local, not internet-facing |
Sources.
Why this verdict
- Friction arithmetic: From vendor 7.8, subtract 1.3 because the attack starts only from an already-compromised low-privileged local session, and subtract 1.0 for absence of public exploit or KEV activity; no role-multiplier floor raises it back.
- Local-only attack surface. The CVSS vector is AV:L/PR:L, so an attacker must already have a low-privileged session on the Mac. That cuts the reachable population to hosts with a compromised or shared local account, not remote attackers.
- No exploit movement. EPSS is 0.00092, KEV is not listed, and no public PoC exists. Real-world exploitation is currently not demonstrated, so a HIGH vendor label overstates the immediate operational risk.
- Role multiplier does not raise the floor. TeamViewer on macOS is normally a member-host/endpoint support tool, not an identity, hypervisor, CA, PAM, or network-edge component. A successful root compromise stops at that host unless the attacker already has further pivots, so the worst plausible role outcome is host-level, not domain/fleet scale.
Why not higher?
Not HIGH/CRITICAL because there is no remote attack vector, no public exploit, no KEV/active exploitation, and the affected component is not a fleet-scale trust boundary. A local root on one Mac is serious, but the preconditions and lack of demonstrated exploitation keep it below drop-everything severity.
Why not lower?
Not LOW/IGNORE because root escalation on endpoint macOS devices can defeat local security controls, steal credentials, and provide a persistent pivot if the host has access to internal resources. The vendor patch is clear and available, so safe cleanup is possible, but the risk is still genuine.
Crowdsourced verification payload.
Run on each macOS target host as any local user; no root needed for version reads. Invoke: bash check_cve_2026_92374.sh. Exit codes: 0 = VULNERABLE, 2 = PATCHED, 1 = UNKNOWN.
#!/bin/bash
# CVE-2026-92374 TeamViewer macOS check. Run on the macOS target host as any user.
# Usage: bash check_cve_2026_92374.sh
set -u
FIXED="15.83"
vuln_found=0
patched_found=0
unknown_found=0
version_key() { echo "$1" | awk -F. '{printf "%d%03d%03d\n", $1, $2, $3}'; }
fixed_key=$(version_key "$FIXED")
for app in "/Applications/TeamViewer.app" "/Applications/TeamViewerHost.app"; do
if [ ! -d "$app" ]; then continue; fi
ver=$(defaults read "$app/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || true)
if [ -z "$ver" ]; then
echo "UNKNOWN: cannot read version from $app"
unknown_found=1
continue
fi
key=$(version_key "$ver")
echo "Found $app version $ver"
if [ "$key" -lt "$fixed_key" ]; then
echo "VULNERABLE: $app version $ver is older than $FIXED"
vuln_found=1
else
echo "PATCHED: $app version $ver is $FIXED or newer"
patched_found=1
fi
done
if [ "$vuln_found" -eq 1 ]; then
echo "RESULT: VULNERABLE"
exit 0
elif [ "$patched_found" -eq 1 ] && [ "$unknown_found" -eq 0 ]; then
echo "RESULT: PATCHED"
exit 2
else
echo "RESULT: UNKNOWN"
exit 1
fi