← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2025-59489 · CWE-88 · Disclosed 2025-10-03

Unity Runtime before 2025-10-02 on Android

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a bad lock on an apartment door inside a building, not an open front gate

CVE-2025-59489 is a Unity Runtime argument-injection flaw that can make a Unity-built app load a library from an unintended path. The vulnerable population is broad in theory: apps built with Unity 2017.1 and later and shipped on Android, Windows, macOS, and Linux before the October 2, 2025 fixes. Unity's own advisory says supported editor branches were fixed on 2025-10-02, while older 2017/2018 lines have no editor patch and instead need rebuild/redeploy or a runtime binary patch path.

The vendor's HIGH rating is technically understandable because the impact inside the target app can be full code execution at that app's privilege level. But for enterprise patch prioritization, reality is narrower: exploitation is fundamentally local or adjacent to local launch/control, there is no KEV listing, Unity says there was no evidence of exploitation, and the EPSS is effectively floor-level. That combination pushes this down from urgent enterprise-wide fire drill to a controlled inventory-and-remediation exercise.

"Serious bug, but it is mostly a post-initial-access/local-launch problem, not an enterprise-wide remote takeover."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Get a way to launch or influence the app locally

The attacker first needs a route to start the vulnerable Unity app with controlled startup data. On Android, the RyotaK research shows this can be a malicious on-device app sending an Intent; on Windows, Unity notes a registered custom URI handler can raise risk if something can cause that URI to open. Weaponized tool: a malicious helper app or URI launcher, not an internet scanner.
Conditions required:
  • Attacker has code execution on the same device, or can install/run a local helper app
  • Or a Windows deployment exposes a custom URI handler tied to the Unity app
Where this breaks in practice:
  • This is not a generic unauthenticated network service
  • Enterprise endpoints often do not expose Unity apps through browser-reachable custom URI handlers
  • Mobile exploitation generally implies a second malicious app is already present
Detection/coverage: Traditional perimeter scanners will miss this. EDR process-creation telemetry, Android mobile threat defense, and URI-handler inventory are the useful controls.
STEP 02

Inject Unity startup arguments

Unity's Android documentation explicitly supports passing startup arguments, and the vulnerable runtime path lets attacker-controlled arguments reach the runtime parser. The research points at the unity extra and the -xrsdk-pre-init-library path as the abuse primitive. Weaponized tool: crafted Intent or crafted launch string based on the documented startup-argument feature.
Conditions required:
  • The target app was built with a vulnerable Unity runtime
  • The attacker can supply startup arguments or equivalent launch metadata
Where this breaks in practice:
  • Platform behavior differs by OS
  • Many apps will never be launched from attacker-controlled wrappers or URIs
  • Some OS hardening and app packaging choices reduce reachable argument paths
Detection/coverage: Look for anomalous parent/child launch chains, suspicious URI invocations, or Android Intents targeting Unity activities.
STEP 03

Force library loading from an attacker-controlled path

Per the research, the vulnerable argument path can feed a library path into runtime loading logic, resulting in unintended shared-library loading. That turns argument injection into code execution inside the app context. Weaponized tool: attacker-supplied .so/DLL/dylib payload referenced by xrsdk-pre-init-library as described in the research write-up.
Conditions required:
  • Attacker can place or reference a loadable library in a reachable path
  • The platform's loading rules permit the target path
Where this breaks in practice:
  • Library placement is another prerequisite beyond merely reaching the app
  • OS controls such as SELinux, code-signing expectations, app sandboxing, and filesystem permissions can reduce practical success
  • Execution stays inside the app's privilege boundary
Detection/coverage: EDR can often catch unsigned or unusual module loads. On Linux/macOS, watch library load events and app launches from untrusted paths.
STEP 04

Operate as the compromised app

Once loaded, the payload executes with the same privileges and data access as the Unity app. On Android that can mean abusing the app's granted permissions; on desktop it usually means user-context execution and access to app data rather than instant system compromise. Weaponized tool: standard post-exploitation payloads running inside the target process.
Conditions required:
  • Successful module load into the vulnerable app
  • Target app has useful data, permissions, or brokered access
Where this breaks in practice:
  • Blast radius is usually limited to one app and one user context
  • No automatic privilege escalation to SYSTEM/root is documented
  • Value depends heavily on what that specific Unity app can access
Detection/coverage: EDR, app-behavior monitoring, unusual file/network access from Unity-based processes, and mobile app permission abuse telemetry are relevant.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusUnity states there was no evidence of exploitation and no user/customer impact in its advisory; the CVE is not KEV-listed.
Proof-of-concept availabilityThere is a public technical write-up by RyotaK of GMO Flatt Security Inc. with exploitation details, and NVD links it with the Exploit tag. Public GitHub detection tooling also exists, e.g. taptap/cve-2025-59489.
EPSS0.017% (4th percentile) per the GitHub advisory's FIRST-fed EPSS display — extremely low short-term exploitation probability.
KEV statusNo. No CISA KEV entry is associated with this CVE in the public catalog.
CVSS splitThere is a scoring mismatch: Unity advisory = 8.4 / AV:L/AC:L; the user-provided 7.4 / AV:L/AC:H aligns with the lower MITRE/NVD primary view. For defenders, the important constant is still AV:L.
Affected versionsUnity says apps built with affected Unity Editor versions from 2017.1 onward are vulnerable on Android, Windows, macOS, Linux Desktop, and Linux Embedded if shipped before the fixes on 2025-10-02.
Fixed versionsSupported branches received first fixed versions such as 2019.1.15f1, 2021.3.56f2, 2022.3.67f2, 6000.0.58f2, 6000.1.17f1, 6000.2.6f2, 6000.3.0b4. Older 2017/2018 lines show N/A for editor patching in the advisory and may need runtime binary patching or application rebuild/redeployment.
Exposure/scanning realityThis is not an internet-listening service. Shodan/Censys-style exposure counts are a poor proxy; you need endpoint software inventory, SBOMs, mobile app catalogs, or build metadata, not perimeter scans.
Platform nuanceAndroid carries the clearest impact path because a malicious on-device app can abuse Unity's argument handling and inherit the target app's permissions. Windows risk increases if the Unity app registers a custom URI handler that an attacker can cause to open.
Disclosure and researcherDiscovered on 2025-06-04 by RyotaK / GMO Flatt Security Inc.; patch available 2025-10-02; public disclosure 2025-10-03.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.7/10)

The single biggest downward pressure is attacker position: this is overwhelmingly a local/post-initial-access bug, not a remotely reachable enterprise edge flaw. The broad affected population matters, but without a local foothold, malicious helper app, or special launch path such as a Windows custom URI handler, most real-world enterprise deployments are not directly exposed.

HIGH Exploit path requires local or local-equivalent launch influence
MEDIUM Enterprise prevalence of vulnerable Unity-built line-of-business apps
MEDIUM Cross-platform impact differences between Android and desktop deployments

Why this verdict

  • AV:L is the whole story: the attack starts from local execution, a second malicious app, or a special local launch vector. That is immediate downward pressure from the vendor baseline.
  • Post-initial-access prerequisites compound: needing on-device code, install rights, or control of a launch/URI path implies the attacker is already on the box or device. EDR, MTD, app allowlisting, and browser controls should break a lot of the chain.
  • No exploitation evidence and floor-level EPSS: Unity reports no observed exploitation, it is not in KEV, and EPSS is 0.017%. That does not make it harmless, but it does argue against emergency-tier prioritization.

Why not higher?

There is no unauthenticated remote entry point here. The exploit chain depends on local execution conditions and app-specific launch semantics, which sharply narrows the exposed population compared with edge RCE or wormable client bugs.

Why not lower?

The impact after successful exploitation is still real: arbitrary code can run inside the target app's trust boundary, and on Android that can mean piggybacking on the victim app's granted permissions. Unity's install base is enormous, so even a local-only bug can matter if you have a meaningful population of Unity-built apps on managed endpoints or mobile fleets.

05 · Compensating Control

What to do — in priority order.

  1. Inventory Unity-built applications — Build a host and mobile app inventory that identifies Unity runtime usage, starting with Windows desktops, managed macOS/Linux endpoints, and Android fleets. Because this is a MEDIUM verdict, there is no mitigation SLA — go straight to the 365-day remediation window, but do the inventory work now so you can separate supported branches from legacy 2017/2018 stragglers.
  2. Constrain untrusted app installation — On Android especially, the exploit value depends on a second malicious app or equivalent local foothold. Tighten enterprise app-store controls, sideloading restrictions, and app allowlisting to reduce the odds of the prerequisite being satisfied before the 365-day remediation window closes.
  3. Audit custom URI handlers — On Windows, Unity explicitly notes custom URI handlers can increase exploitability. Identify Unity-based apps that register schemes, limit which apps may invoke them, and review browser/email launch policies; do this during normal hardening work because there is no mitigation SLA for a MEDIUM finding.
  4. Use EDR to watch module loads and suspicious launch chains — Create detections for Unity-based processes loading unusual DLLs/shared libraries or being launched from odd parents, wrappers, or URIs. This is the practical compensating control when you cannot immediately obtain a rebuilt vendor package, and it should stay in place through the 365-day remediation window.
  5. Press vendors for rebuilt packages — If you rely on third-party Unity applications, ask the publisher for the rebuilt version or proof they applied Unity's runtime patching path. Unsupported 2017/2018 branches are the ugly exception, because the advisory shows N/A editor fixes there even though the vulnerability remains relevant.
What doesn't work
  • Perimeter vulnerability scans: this is not a network service, so internet-facing scanners will give you false comfort.
  • MFA: it helps with identity abuse, not with a malicious local app or local launch path feeding arguments into a Unity runtime.
  • Just patching the Unity Editor on a developer workstation: deployed apps remain vulnerable until the application is rebuilt/redeployed or the runtime library is actually replaced.
06 · Verification

Crowdsourced verification payload.

Run this on an auditor workstation, CI runner, or packaging host where you have a CSV inventory of Unity app versions or know the exact embedded Unity version for a target app. Invoke it as python3 check_unity_cve_2025_59489.py --version 2022.3.61f1 for a single app, or python3 check_unity_cve_2025_59489.py --csv unity_inventory.csv --column unity_version; no admin rights are required.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_unity_cve_2025_59489.py
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/runtime error

import argparse
import csv
import re
import sys
from typing import Optional, Tuple

# First fixed versions from Unity advisory for supported branches.
FIXED = {
    "2019.1": "2019.1.15f1",
    "2019.2": "2019.2.23f1",
    "2019.3": "2019.3.17f1",
    "2019.4": "2019.4.41f1",
    "2020.1": "2020.1.18f1",
    "2020.2": "2020.2.8f1",
    "2020.3": "2020.3.49f1",
    "2021.1": "2021.1.29f1",
    "2021.2": "2021.2.20f1",
    "2021.3": "2021.3.45f2",
    "2022.1": "2022.1.25f1",
    "2022.2": "2022.2.23f1",
    "2022.3": "2022.3.62f2",
    "2023.1": "2023.1.22f1",
    "2023.2": "2023.2.22f1",
    "6000.0": "6000.0.58f2",
    "6000.1": "6000.1.17f1",
    "6000.2": "6000.2.6f2",
    "6000.3": "6000.3.0b4",
}

# Legacy lines noted by Unity as affected but with N/A editor patched versions.
# Version-only checking cannot prove binary-patch status, so these are conservatively VULNERABLE.
LEGACY_VULN_PREFIXES = [
    "2017.1",
    "2017.2",
    "2017.3",
    "2017.4",
    "2018.1",
    "2018.2",
    "2018.3",
    "2018.4",
]

VER_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)([abfp])(\d+)$")
SUFFIX_ORDER = {"a": 0, "b": 1, "f": 2, "p": 3}


def parse_version(v: str) -> Optional[Tuple[int, int, int, int, int]]:
    v = v.strip()
    m = VER_RE.match(v)
    if not m:
        return None
    major, minor, patch, suffix, suffix_num = m.groups()
    return (int(major), int(minor), int(patch), SUFFIX_ORDER[suffix], int(suffix_num))


def branch_of(v: str) -> Optional[str]:
    m = re.match(r"^(\d+)\.(\d+)\.", v.strip())
    if not m:
        return None
    return f"{m.group(1)}.{m.group(2)}"


def compare_versions(a: str, b: str) -> Optional[int]:
    pa = parse_version(a)
    pb = parse_version(b)
    if pa is None or pb is None:
        return None
    return (pa > pb) - (pa < pb)


def assess(version: str) -> Tuple[str, str]:
    version = version.strip()
    branch = branch_of(version)
    if not branch:
        return ("UNKNOWN", f"Unrecognized Unity version format: {version}")

    if branch in LEGACY_VULN_PREFIXES:
        return (
            "VULNERABLE",
            f"{version} is in legacy affected branch {branch}; Unity lists no editor patched version (N/A). Assume vulnerable unless you have explicit proof of runtime binary patching or rebuilt application.",
        )

    fixed = FIXED.get(branch)
    if not fixed:
        return (
            "UNKNOWN",
            f"Branch {branch} is not in the built-in advisory map. Check the Unity advisory manually.",
        )

    cmp_res = compare_versions(version, fixed)
    if cmp_res is None:
        return ("UNKNOWN", f"Could not compare {version} to fixed version {fixed}")
    if cmp_res < 0:
        return ("VULNERABLE", f"{version} is older than fixed version {fixed} for branch {branch}")
    return ("PATCHED", f"{version} is at or newer than fixed version {fixed} for branch {branch}")


def process_single(version: str) -> int:
    status, detail = assess(version)
    print(status)
    print(detail)
    return {"PATCHED": 0, "VULNERABLE": 1, "UNKNOWN": 2}[status]


def process_csv(path: str, column: str) -> int:
    worst = 0
    seen = 0
    with open(path, newline="", encoding="utf-8-sig") as fh:
        reader = csv.DictReader(fh)
        if column not in reader.fieldnames:
            print("UNKNOWN")
            print(f"CSV missing required column: {column}")
            return 2
        for row in reader:
            seen += 1
            version = (row.get(column) or "").strip()
            asset = row.get("asset") or row.get("name") or row.get("app") or f"row-{seen}"
            if not version:
                status, detail = ("UNKNOWN", "No Unity version present")
            else:
                status, detail = assess(version)
            print(f"{asset},{version},{status},{detail}")
            rc = {"PATCHED": 0, "VULNERABLE": 1, "UNKNOWN": 2}[status]
            worst = max(worst, rc)
    if seen == 0:
        print("UNKNOWN")
        print("CSV contained no rows")
        return 2
    print(["PATCHED", "VULNERABLE", "UNKNOWN"][worst if worst < 3 else 2])
    return worst


def main() -> int:
    parser = argparse.ArgumentParser(description="Check Unity versions for CVE-2025-59489 exposure")
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--version", help="Single Unity version, e.g. 2022.3.61f1")
    group.add_argument("--csv", help="CSV file with Unity versions")
    parser.add_argument("--column", default="unity_version", help="CSV column name for the Unity version (default: unity_version)")
    args = parser.parse_args()

    try:
        if args.version:
            return process_single(args.version)
        return process_csv(args.csv, args.column)
    except FileNotFoundError as e:
        print("UNKNOWN")
        print(f"File not found: {e}")
        return 3
    except Exception as e:
        print("UNKNOWN")
        print(f"Runtime error: {e}")
        return 3


if __name__ == "__main__":
    sys.exit(main())
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not treat this like an internet-edge emergency; treat it like a broad client inventory problem. Use your software inventory, SBOM, mobile app catalog, and EDR telemetry to find Unity-built applications, prioritize any Android fleet exposure and Windows apps with custom URI handlers, and start collecting rebuilt packages from internal teams or software vendors. For a MEDIUM reassessment there is noisgate mitigation SLA: no mitigation SLA — go straight to the 365-day remediation window; the noisgate remediation SLA is ≤365 days to get affected apps rebuilt, redeployed, or otherwise replaced, with unsupported 2017/2018 packages called out as exception cases that deserve earlier manual handling.

Sources

  1. Unity Security Update Advisory
  2. NVD CVE-2025-59489
  3. CVE.org record
  4. GMO Flatt Security research by RyotaK
  5. Unity documentation: Android player command-line arguments
  6. GitHub Advisory Database entry
  7. CISA Known Exploited Vulnerabilities Catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.