Neutron, our AI engine, scored 97.1% on UC Berkeley's CyberGym benchmark. Learn more

Deep Dive

Deep Dive

Xen Hypervisor Guest Escape (CVE-2026-102703, CVE-2026-102704)

Two grant-copy validation flaws let a malicious Xen guest read and write the memory of other domains, including Dom0; apply the XSA-523 patches now.

TL;DR

  • Two validation flaws in Xen's grant-copy operations let a malicious guest read and write memory belonging to other domains, including Dom0, the control domain. The Xen Project published advisory XSA-523 on November 3, 2026.
  • Every Xen version from 4.6 onwards is affected, and Xen 4.5 and earlier are not. There is no known mitigation.
  • The advisory gives no CVSS score. No exploitation is known, and neither CVE is in the Cybersecurity and Infrastructure Security Agency (CISA) Known Exploited Vulnerabilities (KEV) catalog as of November 4, 2026.
  • Apply the XSA-523 patches for 4.17 through unstable to the tip of your stable branch, or take your platform vendor's update. No Xen release tarball carries them yet. See "How do I fix it?".

Am I affected?

You are exposed when all of these hold:

  • You run the Xen hypervisor, version 4.6 or any later release. The advisory states all versions from 4.6 onwards are vulnerable, and that 4.5 and earlier are not.
  • Your deployment runs untrusted guests. Any guest operating a grant table can issue the vulnerable copy operations.
  • You have not yet applied the XSA-523 patches. The advisory's resolution is the patch set; no Xen release tarball carries it as of November 4, 2026.

Guests themselves are the attacker here, not the victim of a network attacker. A guest whose memory is read or written by a malicious neighbor sees no indicator of it.

Branch Affected versions Fix
xen-unstable, 4.22.x to 4.19.x All releases xsa523-1.patch, xsa523-2.patch
4.18.x to 4.17.x All releases xsa523-4.18-1.patch, xsa523-4.18-2.patch
4.6.x to 4.16.x All releases No patch from the Xen Project; these branches are end of life

XCP-ng is a Xen Project platform, and its documentation says it is built around the Xen hypervisor. Check what your host actually runs:

# On the host (dom0): the running Xen version
xl info | grep '^xen_version'

# In a Linux guest: confirms the hypervisor type (prints "Xen" under Xen)
cat /sys/hypervisor/type 2>/dev/null

# In a Linux guest: the hypervisor version the guest was told
cat /sys/hypervisor/version/major 2>/dev/null
cat /sys/hypervisor/version/minor 2>/dev/null

The version shows whether a host is in the affected range, and every release from 4.6 onwards is in it. It cannot show whether the XSA-523 patches are applied, because no release carries them. Check your vendor's advisory or package changelog for XSA-523 instead.

On a managed cloud the guest's view may lag the host's patch state. Ask your provider for the host's XSA-523 status if you run untrusted tenants on it.

How do I fix it?

  1. If you build Xen from a stable branch, update to the tip of the branch first, then apply the XSA-523 patches. Rebuild Xen and reboot the host into the patched hypervisor. The advisory notes the patches are prepared for the stable branches and may not apply cleanly to a release tarball.
  2. If you run a packaged Xen from a platform vendor or distribution, apply the vendor's update when it ships, then reboot the host. No released Xen tarball carried the fix as of November 4, 2026.
  3. Recreate guests only as your recovery plan requires. Applying the hypervisor patch stops future attacks; it does not tell you whether an earlier one happened.

There is no configuration workaround. The advisory says: "There is no known mitigation."

What is the root cause?

The grant-copy hypercall lets a guest copy data between grant references and machine frame numbers. For performance, commit d28f42f2703e ("grant-table: defer releasing pages acquired in a grant copy") made Xen cache the validated description of the previous batch element. That commit first shipped in Xen 4.6.0, which matches the advisory's vulnerable range.

A batch of grant-copy operations often acts on adjacent address ranges in the same source or destination page. The cache is reused when the next element looks equivalent. The advisory describes both flaws as incorrect conditions for that reuse.

CVE-2026-102703 is the cache-validity check. In gnttab_copy_buf_valid(), p is the new element's source or destination, and b is the cached buffer. has_gref says whether the new element uses a grant reference (GREF). The vulnerable code is xen/common/grant_table.c, lines 3082 to 3091, in xen-unstable before the patches:

static bool gnttab_copy_buf_valid(
    const struct gnttab_copy_ptr *p, const struct gnttab_copy_buf *b,
    bool has_gref)
{
    if ( !b->virt )
        return 0;
    if ( has_gref )
        return b->have_grant && p->u.ref == b->ptr.u.ref;
    return p->u.gmfn == b->ptr.u.gmfn;
}

The ->have_grant field records whether the cached entry came from a grant reference. The code checks it only on the grant-reference path, ahead of comparing GREFs. The machine-frame path compares p->u.gmfn == b->ptr.u.gmfn without checking that the cached entry was also a frame entry.

The patch description states the consequence: a (likely invalid) GREF from an earlier batch element can be mistaken for a (possibly valid) machine frame number (MFN).

CVE-2026-102704 is the permission check. Copying by frame number, rather than by grant reference, is permitted only when operating on the caller's own memory. Before the patches, gnttab_copy_lock_domain() enforces this, at lines 2939 to 2946 of the same file:

static int gnttab_copy_lock_domain(domid_t domid, bool is_gref,
                                   struct gnttab_copy_buf *buf)
{
    /* Only DOMID_SELF may reference via frame. */
    if ( domid != DOMID_SELF && !is_gref )
        return GNTST_permission_denied;

    buf->domain = rcu_lock_domain_by_any_id(domid);

gnttab_copy_one() reaches that check only when it locks the domains again, at lines 3140 to 3150. Here op is the current batch element, and src and dest are the cached source and destination buffers:

    if ( !src->domain || op->source.domid != src->ptr.domid ||
         !dest->domain || op->dest.domid != dest->ptr.domid )
    {
        gnttab_copy_release_buf(src);
        gnttab_copy_release_buf(dest);
        gnttab_copy_unlock_domains(src, dest);

        rc = gnttab_copy_lock_domains(op, src, dest);
        if ( rc < 0 )
            goto out;
    }

An element that names the same domains as the previous element skips this block. Its frame-number copy is then never checked against DOMID_SELF.

How is it exploited?

For CVE-2026-102703:

  1. The malicious guest issues a GNTTABOP_copy batch. An early element copies by grant reference, so the cache holds a validated grant entry.
  2. A later element in the same batch copies by machine frame number, so Xen compares its frame number with the cached entry.
  3. The comparison does not check that the cached entry was a frame entry. The earlier grant reference is mistaken for a frame number, and Xen reuses the cached buffer.
  4. The copy then reads or writes memory the guest cannot legitimately address, belonging to other domains, including Dom0.

For CVE-2026-102704:

  1. The malicious guest issues a copy batch. An early element names a foreign domain by grant reference, which passes the check, and Xen locks that domain.
  2. A later element names the same domain but copies by frame number. gnttab_copy_one() skips the domain-locking step, so the "only DOMID_SELF may reference via frame" check never runs.
  3. The guest addresses memory of another domain by machine frame number directly, without a grant.

Both paths need no special guest configuration, only a functioning grant table. No proof of concept is public, and the patches themselves document the reachable behavior.

How does the attack flow?

A batch of grant-copy operations reuses cached state, and either of two missing per-element checks lets the guest address another domain's memory.

flowchart LR A["Malicious guest issues
GNTTABOP_copy batch"] --> B["Earlier element validated
by grant reference"] B --> C["Later element copies
by frame number"] C --> D["CVE-2026-102703: no addressing-mode check,
GREF taken as a frame number"] C --> E["CVE-2026-102704: domains not relocked,
no DOMID_SELF check"] D --> F["Read or write other domains'
memory, including Dom0"] E --> F

What can an attacker do?

In the advisory's words, a malicious guest can read and write arbitrary memory belonging to other domains, including Dom0. That is the strongest statement the sources support.

In practice, that access could expose secrets held in another guest's memory or change another guest's code and data. No public source demonstrates such an attack. The advisory gives no CVSS score, and no real-world abuse is reported.

The attacker needs control of a guest on an unpatched host. Hosts that run only trusted guests are exposed only if one of those guests is compromised first.

Why does the fix work?

The patch for CVE-2026-102703 refuses cache reuse when the new element's addressing mode differs from the cached one:

 static bool gnttab_copy_buf_valid(
     const struct gnttab_copy_ptr *p, const struct gnttab_copy_buf *b,
     bool has_gref)
 {
-    if ( !b->virt )
+    if ( !b->virt || b->have_grant != has_gref )
         return 0;
     if ( has_gref )
-        return b->have_grant && p->u.ref == b->ptr.u.ref;
+        return p->u.ref == b->ptr.u.ref;
     return p->u.gmfn == b->ptr.u.gmfn;
 }

A grant reference can no longer be compared against, or mistaken for, a machine frame number. The check is complete for the reported flaw: the cache is only consulted when the addressing modes match.

The patch for CVE-2026-102704 removes the DOMID_SELF check from gnttab_copy_lock_domain() and adds it to gnttab_copy_claim_buf():

         buf->ptr.u.ref = ptr->u.ref;
         buf->have_grant = 1;
     }
+    /* Only DOMID_SELF may reference via frame. */
+    else if ( ptr->domid != DOMID_SELF )
+        return GNTST_permission_denied;
     else
     {
         rc = get_paged_frame(ptr->u.gmfn, &buf->mfn, &buf->page,

gnttab_copy_claim_buf() runs whenever an element cannot reuse the cached buffer. The permission check therefore no longer depends on whether the domain-locking step ran.

With both patches, every batch element passes two guards before it reuses anything:

flowchart LR A["New batch element"] --> B{"Same addressing mode
as the cache?"} B -- "no" --> C["Cache refused,
full validation runs"] B -- "yes" --> D{"Copies by frame naming
a foreign domain?"} D -- "yes" --> E["GNTST_permission_denied
for the element"] D -- "no" --> F["Copy proceeds on the
validated buffer"]

How do I check if I was compromised?

No indicators are published. The advisory describes no detection signature, and a cross-domain memory read or write leaves no trace a victim guest can see.

On the host, the attack is a guest issuing ordinary grant-copy hypercalls, which look like normal grant-table activity in logs. Hosts that ran untrusted guests before applying the patch should treat tenant secrets as potentially exposed, and should ask their Xen vendor about detection support.

Timeline

  • 2015-01-29: Commit d28f42f2703e adds the grant-copy cache to the Xen tree.
  • 2015-10-07: The Xen Project tags Xen 4.6.0, the first release that contains the commit.
  • 2026-11-03: The Xen Project releases XSA-523 version 2 publicly at 12:00 UTC, with patches for Xen 4.17 through unstable and the two CVE ids.

FAQ

Does this affect KVM, Hyper-V or VMware hosts?

No. The flaws live in Xen's grant-table code, which is specific to the Xen hypervisor. Hosts on other hypervisors are not affected.

Are the CVE records published?

No. As of November 4, 2026, the CVE database carries no record for CVE-2026-102703 or CVE-2026-102704. The advisory names both ids, so reference the advisory until the records publish.

Who found the bug?

Anthropic discovered it using Claude, and Stephan Lipp of Ada Logics validated the finding, per the advisory's credits. The CodeAnt AI Security Research Team reported it independently. The fix patches carry an "Assisted-by: Claude" line. The advisory does not give the date of the first report.

I run an end-of-life branch, 4.16 or earlier. What do I do?

The Xen Project provides no patches for those branches. Move to a maintained branch, 4.17 or later, and apply the XSA-523 patches to it.

My cloud provider runs Xen. Do I need to act?

You cannot patch a provider's host from a guest. Ask the provider for its XSA-523 status, and treat cross-tenant secrets as the provider's responsibility until it confirms the patch.

Find and patch your Xen hosts before a tenant exploits them

Hosts running Xen for untrusted guests are the exposure here, and the attacker is a tenant on the same host, not a scanner on the internet. Ostorlab's attack surface discovery inventories the servers and management interfaces you expose to the internet, which gives you a first list of Xen hosts to check for XSA-523. Hosts reachable only from your internal network need your own inventory.

References

  • Xen Security Advisory 523 version 2, "arbitrary read/write via grant copy", public release 2026-11-03: https://xenbits.xenproject.org/xsa/advisory-523.html (checked November 4, 2026)
  • XSA-523 patch 1, "gnttab: complete checking in gnttab_copy_buf_valid()", CVE-2026-102703: https://xenbits.xenproject.org/xsa/xsa523-1.patch (checked November 4, 2026)
  • XSA-523 patch 2, "gnttab: move 'only local domain may copy by frame' check", CVE-2026-102704: https://xenbits.xenproject.org/xsa/xsa523-2.patch (checked November 4, 2026)
  • OSS Security mailing list copy of XSA-523 version 2: https://www.openwall.com/lists/oss-security/2026/11/03/6 (checked November 4, 2026)
  • Xen source, xen/common/grant_table.c before the XSA-523 patches (commit c89185286cbe): https://github.com/xen-project/xen/blob/c89185286cbe74f584e2ddca9bfa6654a8600502/xen/common/grant_table.c (checked November 4, 2026)
  • Xen commit d28f42f2703e, "grant-table: defer releasing pages acquired in a grant copy", 2015-01-29: https://github.com/xen-project/xen/commit/d28f42f2703e483116bafd2b0b76a32af67d83ad (checked November 4, 2026)
  • Xen 4.6.0 release tag, RELEASE-4.6.0, 2015-10-07: https://github.com/xen-project/xen/releases/tag/RELEASE-4.6.0 (checked November 4, 2026)
  • Xen Project, XCP-ng project page: https://xenproject.org/projects/xcp-ng/ (checked November 4, 2026)
  • XCP-ng documentation, "XCP-ng contains multiple components, built around the Xen Hypervisor": https://docs.xcp-ng.org/ (checked November 4, 2026)
  • CISA Known Exploited Vulnerabilities catalog, JSON feed, searched for both CVE ids: https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (checked November 4, 2026)