This is a booby-trapped deep link, not an internet worm
CVE-2026-47114 is an argument-injection bug in IINA's iina://open custom URL handler on macOS. In versions before 1.4.3, attacker-controlled mpv_ query parameters can reach mpv runtime options, and the dangerous confirmed path is mpv_options/input-commands=run, which can execute arbitrary commands as the currently logged-in user. The public advisory and vendor fix both point to the same browser-delivered flow: a malicious iina:// link, user approval of the browser protocol prompt, then command execution without needing a valid media file.
The vendor's HIGH 8.8 score is technically defensible in a lab because the impact is full user-context code execution from a remote lure. Operationally, though, this is not a broad enterprise emergency: it requires a macOS endpoint, IINA installed, a user click, a second user approval step, and it lands only in that user's session with no privilege escalation. That stack of friction materially narrows exposure, so the right call for fleet patching is MEDIUM, not HIGH.
4 steps from start to impact.
Deliver a malicious iina://open link
iina://open?... URL that embeds mpv_-prefixed parameters. The public advisory from *stackpointer* includes a working example that passes mpv_options/input-commands=run to the target app. Tooling here is trivial: email lure, chat message, or webpage plus the crafted custom-protocol URL.- Target is on macOS
- IINA is installed and registered for the
iina://protocol - User can be induced to click an untrusted link
- IINA is a niche desktop app, not a ubiquitous enterprise dependency
- This is not remotely reachable without user interaction
- Mail filtering, browser reputation, and user training can kill the lure before execution
iina://open URLs in user-facing content.User approves browser-to-app handoff
- User clicks the lure
- User accepts the browser protocol prompt to open IINA
- This is a second conscious user action beyond the initial click
- Some enterprise browsers or hardening policies can restrict external protocol handlers
IINA forwards unsafe mpv_ options into mpv
mpv_ query names and forwards them into player.mpv.setString(...). The fix commit specifically adds a guard to reject option names containing input-command, confirming the vulnerable trust boundary. The weaponized primitive is mpv's input-commands option, referenced in issue #6083 and the public advisory.- IINA version is below 1.4.3
- The URL contains attacker-chosen
mpv_parameters
- Exploitability depends on a specific dangerous mpv option path, not generic command injection everywhere
- The vendor shipped a simple, targeted fix, which limits long-term exploit shelf life
mpv executes attacker-chosen commands as the logged-in user
input-commands=run ... reaches mpv, arbitrary commands execute in the user's context. The public proof uses benign filesystem actions like touch /tmp/pwned, but the same primitive can stage a payload, beacon, or modify user data. There is no evidence in the sourced material of privilege escalation beyond the current user session.- Dangerous mpv option accepted by vulnerable IINA
- User context has normal access to home directory, keychain prompts, browser tokens, etc.
- Impact is limited to the local user account unless chained with another privilege-escalation bug
- EDR should catch suspicious child processes from
IINA.appsuch assh,osascript,curl, orpython
IINA.app spawning shell or scripting interpreters. Traditional network scanners will miss this class entirely.The supporting signals.
| In-the-wild status | No sourced evidence of active exploitation in the materials reviewed. Not in CISA KEV as of the current KEV catalog. |
|---|---|
| Proof-of-concept availability | Yes. Researcher stackpointer published a public advisory with working iina://open examples and a demo video: stackpointer advisory, mirrored in vendor issue #6083. |
| EPSS | User-supplied EPSS is 0.00172, which is very low. I did not independently verify the exact percentile from a primary source in this session. |
| KEV status | No. No KEV entry or federal due date is present in CISA's Known Exploited Vulnerabilities Catalog. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H from NVD/VulnCheck. Translation: remote delivery is possible, but user interaction is mandatory. |
| Affected versions | IINA before 1.4.3 on macOS, with the public advisory confirming 1.4.2 and stating the bug appears to have existed since 2018: advisory. |
| Fixed version | Patched in IINA 1.4.3. The official release notes call out a fix for command injection when opening an iina:// URL: 1.4.3.html" target="_blank" rel="noopener">IINA 1.4.3 release note, 1.4.3" target="_blank" rel="noopener">GitHub release, fix commit. |
| Scanning / exposure data | This is a desktop app custom-protocol issue, not an exposed server socket. Internet census platforms like Shodan/Censys are the wrong lens here; exposure is driven by how many managed Macs have IINA installed and whether browsers may hand off iina:// links. |
| Disclosure / researcher | Publicly disclosed 2026-05-21 in the CVE record, credited to stackpointer. The GitHub security bug report was opened 2026-05-19, and the fix landed 2026-05-20: NVD, issue #6083. |
noisgate verdict.
The decisive downgrade factor is the double user-action requirement: the target must both click the lure and approve the browser's custom-protocol prompt before anything happens. This is real code execution, but it is confined to a comparatively small population of macOS endpoints running IINA and does not provide privilege escalation or wormable reach.
Why this verdict
- Start from 8.8, then subtract for user friction: the vendor baseline assumes remote code execution impact, but the attack requires a browser-delivered lure and explicit approval of the
iina://handoff prompt. - Population is naturally limited: only macOS devices with IINA installed are exposed. This is not Safari, Chrome, Office, or another near-universal enterprise app, so reachable population is materially smaller.
- Blast radius is one user session: execution is as the current macOS user. There is no sourced evidence of privilege escalation, cross-user compromise, or server-side multi-tenant impact.
- No exploitation evidence: not KEV-listed, no campaign reporting in sourced material, and the user-supplied EPSS is very low.
Why not higher?
Because this is not unauthenticated drive-by exploitation of an always-on service. The attack chain narrows hard at every stage: macOS only, IINA installed, user clicks, user approves protocol launch, then code runs only in that user's context. That is meaningful risk, but not a fleet-level HIGH absent exploitation pressure.
Why not lower?
Because once the chain succeeds, the attacker gets arbitrary command execution on the endpoint. This is not a cosmetic bug or a harmless crash; it is initial-access-grade code execution against the local user. Public PoC material exists, so defenders should not write it off as theoretical.
What to do — in priority order.
- Block risky external-protocol launches from browsers — If your macOS browser management stack supports it, restrict or warn on handoff to non-business-critical custom URL schemes such as
iina://. For a MEDIUM verdict there is no mitigation SLA; use the next normal policy cycle if patch rollout will lag, and keep the real patch inside the 365-day remediation window. - Hunt for
IINA.appspawning shells or script engines — Create EDR analytics for parentIINA.applaunchingsh,bash,zsh,osascript,python,curl, orrm. This is the most practical compensating control because the exploit path eventually has to turn into a child process; for MEDIUM, there is no mitigation SLA, so deploy as standard detection engineering rather than emergency change. - Inventory IINA across managed Macs — Treat this as an application-specific exposure problem, not a generic macOS problem. Query MDM, EDR software inventory, or package receipts to identify hosts with IINA below 1.4.3; with a MEDIUM verdict there is no mitigation SLA, so this can run as routine hygiene while you plan remediation within 365 days.
- Prefer allow-listed media players in managed environments — Where IINA is not business-required, standardize on approved software and remove niche user-installed players from managed fleets. This reduces future custom-protocol and plugin attack surface; again, MEDIUM means no mitigation SLA, so handle it through normal software governance.
- Generic perimeter firewalls do nothing here because there is no inbound network service to block.
- WAF rules are irrelevant; the vulnerable surface is a local macOS app protocol handler, not a web application endpoint.
- MFA does not meaningfully help because exploitation targets the local endpoint after a user opens a link, not an authentication workflow.
Crowdsourced verification payload.
Run this on the target macOS host or through your MDM/EDR remote shell. Invoke it as bash check_iina_cve_2026_47114.sh with no elevated privileges required for standard app locations; it checks common IINA install paths and prints VULNERABLE, PATCHED, or UNKNOWN.
#!/bin/bash
# check_iina_cve_2026_47114.sh
# Detects whether installed IINA versions are vulnerable to CVE-2026-47114.
# Vulnerable: versions before 1.4.3
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET_VERSION="1.4.3"
FOUND_ANY=0
FOUND_VULN=0
FOUND_PATCHED=0
CANDIDATES=(
"/Applications/IINA.app"
"$HOME/Applications/IINA.app"
)
get_version() {
local app="$1"
local plist="$app/Contents/Info.plist"
local version=""
if [[ ! -f "$plist" ]]; then
echo ""
return 0
fi
version=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$plist" 2>/dev/null || true)
if [[ -z "$version" ]]; then
version=$(defaults read "${plist%.plist}" CFBundleShortVersionString 2>/dev/null || true)
fi
echo "$version"
}
# compare_versions a b
# returns:
# 0 if a == b
# 1 if a > b
# 2 if a < b
compare_versions() {
local a="$1"
local b="$2"
local IFS=.
local i
local -a va vb
read -r -a va <<< "$a"
read -r -a vb <<< "$b"
local len=${#va[@]}
if [[ ${#vb[@]} -gt $len ]]; then
len=${#vb[@]}
fi
for (( i=0; i<len; i++ )); do
local ai=${va[i]:-0}
local bi=${vb[i]:-0}
# strip non-numeric suffixes conservatively
ai=${ai%%[^0-9]*}
bi=${bi%%[^0-9]*}
[[ -z "$ai" ]] && ai=0
[[ -z "$bi" ]] && bi=0
if (( 10#$ai > 10#$bi )); then
return 1
elif (( 10#$ai < 10#$bi )); then
return 2
fi
done
return 0
}
for app in "${CANDIDATES[@]}"; do
if [[ -d "$app" ]]; then
FOUND_ANY=1
version=$(get_version "$app")
if [[ -z "$version" ]]; then
continue
fi
compare_versions "$version" "$TARGET_VERSION"
rc=$?
if [[ $rc -eq 2 ]]; then
FOUND_VULN=1
echo "VULNERABLE"
exit 1
else
FOUND_PATCHED=1
fi
fi
done
if [[ $FOUND_PATCHED -eq 1 ]]; then
echo "PATCHED"
exit 0
fi
if [[ $FOUND_ANY -eq 1 ]]; then
echo "UNKNOWN"
exit 2
fi
echo "UNKNOWN"
exit 2
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.