TL;DR

Xoscar, the Python actor framework that Xinference's supervisor and workers talk through, accepted a message on its actor-pool TCP channel and passed it to cloudpickle.loads() before checking the message type, so anyone who could reach the port ran code as the server process, which the record says commonly runs as root on GPU nodes (CVE-2026-49950, VulnCheck CNA, 2026-10-13, CVSS 4.0 9.3, 3.1 9.8; reporter Valentin Lobstein). Affected 0.1.0 through 0.11.2. Xoscar 0.12.0 (PyPI 2026-10-16) adds HMAC-SHA256 authentication of every frame, checked before deserialization, for the Socket and UCX transports, and Xinference 4.0.1 (same day) requires it. Authentication is off until XOSCAR_AUTH_KEY is set to the same non-empty value on every process; the release notes say so, and keyed and unkeyed processes cannot talk, so turning it on is a coordinated restart. An upgrade with no further action changes nothing about who can reach the actor port. Xinference's HTTP API key does not protect the actor ports either. Three earlier Xinference records this year (a 10.0 eval() in Llama3 tool-call parsing fixed in 2.7.0, trust_remote_code hard-wired on before 2.12.0, an unauthenticated file read in 3.3.0) had no file here and are listed below.

What happened

Xinference (xorbitsai/inference, PyPI xinference) is a self-hosted model-serving platform that runs LLM, embedding, rerank, speech and image models behind an OpenAI-compatible API, and it is one of the serving layers a self-hosted RAG or agent backend ends up on. Its processes are actors: the supervisor, each worker and each model are Xoscar actors exchanging messages over TCP (and UCX on supported hardware). VulnCheck's record for CVE-2026-49950 says SocketChannel.recv() hands received bytes to cloudpickle.loads() with no validation, and a pickle __reduce__ gadget runs "before message type validation," giving remote code execution as the process; the two references are the serialization core and the socket backend at v0.11.2. The advisory page lists only the publication date, 2026-10-13, and names no fixed version. It does not mention Xinference; the dependency link is from Xinference's own release notes and package metadata.

The vendor's response is on the two release pages. Xoscar v0.12.0 (2026-10-16) has a Security section: opt-in HMAC-SHA256 authentication for the Socket and UCX transports, covering framing metadata, the serialized header and every payload buffer, verified "before deserializing Python objects"; unauthenticated, mis-keyed and tampered messages are rejected; "Authentication is disabled by default"; when XOSCAR_AUTH_KEY is unset or empty the legacy wire format and v0.11.2 compatibility are preserved; keyed and unkeyed processes cannot communicate and there is no mixed-mode rolling upgrade. The notes link the CVE. Xinference v4.0.1 (2026-10-16) raises the dependency to xoscar>=0.12.0 in the package and the CPU image, passes the key through the standalone and distributed Docker Compose files, and states that actor transport authentication is off unless a non-empty XOSCAR_AUTH_KEY is set, that upgrading alone does not enable it, and that HTTP API authentication does not protect actor ports. PyPI confirms the pin: xinference 4.0.1 requires xoscar>=0.12.0.

So the fix is real and the default is off. This file follows the sweep's rule for a fix that the default leaves off: status mitigated, where the operator sets the key, not patched. The same shape appears in sandboxed.sh's opt-in flag and in the MCP SDKs' audience checks, filed under their own files' statuses because other findings in those files set them; here the opt-in authentication is the whole fix. Whether the unauthenticated path still deserializes untrusted bytes when no key is set is answered by the compatibility sentence: the legacy wire format is preserved, so yes. A deployment that upgrades and does nothing else is in the same position as before.

Three Xinference records from August and September were untracked here and belong beside this one, because they describe the same product's other inputs:

  • CVE-2026-61539 (GitHub CNA, 2026-08-21, CVSS 3.1 10.0; vendor advisory GHSA-x2rj-828p-hx9m): Xinference passed model-generated Llama3 tool-call output to eval() in the tool parser, reachable from /v1/chat/completions with a tools field; the record says affected before 2.7.0 and the description says 2.5.0 and earlier; fixed in 2.7.0 (PR #4786). A model's output is attacker-influenced through the prompt, so this is prompt injection to code execution on the serving host.
  • CVE-2026-76841 (VulnCheck, 2026-08-24, 8.7): six loader call sites passed trust_remote_code=True as a literal or unconditional default, so any model repository's custom code ran at load with no setting to disable it before 2.12.0 (PR #5027).
  • CVE-2026-85668 (VulnCheck, 2026-09-04, 8.7): POST /v1/models/llm/auto-register took a caller-supplied model_path with no authentication and no path confinement and reflected the parsed config.json, tokenizer_config.json and chat_template.jinja from any directory; the record names 3.3.0 and commit 4a94832 and no fix (issue #5176).

Xinference's own tab also carries GHSA-jv65-rccw-j2j6, fixed in 3.5.0 (2026-09-25), for a custom-model registration that could claim built-in provenance and bypass the repository-code restriction; the release page says to check saved registrations for an unexpected is_builtin: true, because the patch does not rewrite old ones. That one has no CVE and was read from the releases page only.

Severity here is high against the CNA's 9.3. The actor port must be reachable: a single-host install that binds its actor transport to loopback is reached only from the host, a distributed install with workers on other machines exposes it on whatever interface the operator chose, and the record's "commonly runs as root on GPU nodes" is the blast radius once reached. The Hacker News front page carried a Medium post on 2026-10-17 titled "CVE-2026-49950 and Why Upgrading Xinference Isn't Enough"; the page returned 403 to this sweep and is not cited, but its title matches what the two release pages say.

Am I affected?

pip show xoscar xinference 2>/dev/null | grep -iE '^(name|version)'   # xoscar <= 0.11.2 is CVE-2026-49950; 0.12.0 fixes nothing until keyed
# xinference < 2.7.0: CVE-2026-61539; < 2.12.0: CVE-2026-76841; 3.3.0 line: CVE-2026-85668 (no fix stated); < 3.5.0: GHSA-jv65-rccw-j2j6
echo "XOSCAR_AUTH_KEY set: ${XOSCAR_AUTH_KEY:+yes}"                    # empty on any process = authentication off on that process
ss -ltnp 2>/dev/null | grep -iE 'xinference|xoscar|python'           # actor ports bound to 0.0.0.0 are reachable by whoever can route to the host

Affected if any process runs xoscar 0.11.2 or earlier with an actor port reachable off-host, or runs 0.12.0 or later with the key unset on any process in the cluster. Not affected only if every actor port is loopback-only or every process carries the same non-empty key.

If you are affected

Upgrade to xoscar 0.12.0 and Xinference 4.0.1 or later, then set XOSCAR_AUTH_KEY to the same high-entropy value on every supervisor and worker and restart them together; the release notes say a rolling upgrade is not supported, and a half-keyed cluster stops talking rather than falling back. Until then, bind the actor transports to loopback or a private network with no route from clients, and run the processes as a non-root user. If an actor port was reachable from an untrusted network while unauthenticated, treat the host as compromised: rebuild, rotate the model-provider and cloud credentials it held per rotating-cloud-credentials.md, and follow if-your-webapp-was-compromised.md. For the Xinference records, move to 3.5.0 or later, audit saved custom-model registrations for is_builtin: true, and do not load model repositories you did not vet.

Prevention

  • An inference platform's inter-process ports are a control plane; isolate them and authenticate them, and read the release notes for the word "default" before counting an upgrade as a fix (supply-chain-attack-surface.md).
  • Run model servers in a container with no other credentials and a non-root user (agent-sandboxing.md); the record's root-on-GPU-node observation is the deployment pattern, not the bug.
  • Model repositories are code when trust_remote_code is on; vet them like packages (package-vetting-checklist.md).

Sources

  • VulnCheck, Xorbits Xoscar 0.11.2 Unauthenticated Deserialization RCE via Actor Pool — 2026-10-13; CVE-2026-49950, 9.3, range 0.1.0 through 0.11.2, no fixed version, the two code references, credit; Xinference not named.
  • CVE-2026-49950, CVE Services record (VulnCheck CNA) — published 2026-10-13, updated 2026-10-16; 9.3 and 9.8 vectors, "commonly runs as root on GPU nodes."
  • xorbitsai/xoscar release v0.12.0 — 2026-10-16; the Security section: HMAC-SHA256 on Socket and UCX, verified before deserialization, "Authentication is disabled by default," XOSCAR_AUTH_KEY, no mixed-mode upgrade, CVE link. Releases index — v0.11.2 (2026-10-07), v0.11.1, v0.11.0 carry no security notes.
  • xorbitsai/inference releases — v4.0.1 (2026-10-16): requires Xoscar 0.12.0, key pass-through in Compose, "upgrading alone doesn't enable it," HTTP API auth does not protect actor ports; v3.5.0 (2026-09-25): GHSA-jv65-rccw-j2j6 and the is_builtin check.
  • PyPI metadata, queried 2026-10-17: xoscar 0.11.2 uploaded 2026-10-07, 0.12.0 on 2026-10-16, latest; xinference 4.0.1 uploaded 2026-10-16 with xoscar>=0.12.0 in requires_dist.
  • CVE Services records, fetched 2026-10-17: CVE-2026-61539 (GitHub CNA, 10.0, before 2.7.0, PR #4786), CVE-2026-76841 (VulnCheck, 8.7, before 2.12.0, PR #5027), CVE-2026-85668 (VulnCheck, 8.7, 3.3.0, issue #5176, no fix).
  • GitHub Advisory Database, query xinference — five rows on 2026-10-17, all unreviewed; none for CVE-2026-49950, which is filed against xoscar.
  • Hacker News, 2026-10-17: "CVE-2026-49950 and Why Upgrading Xinference Isn't Enough" (Medium) — the page returned 403 to this sweep; title only, not cited for any fact.
  • Related in this corpus: LMCache CVE-2026-105192, the SGLang July to October wave.