This is a booby-trapped service hatch inside the vault, not an unlocked front door
CVE-2026-40290 is a use-after-free race in OP-TEE's FF-A shared-memory teardown logic, specifically in the SPMC/SP code paths used when OP-TEE is acting as an S-EL1 SPMC for S-EL0 Secure Partitions. The GitHub advisory says affected versions are >= 3.16.0 and fixed versions are 4.11 and later, but the bug only exists when CFG_SECURE_PARTITION=y is enabled, which materially narrows the exposed population.
The vendor's HIGH 7.8 score is technically defensible in a lab because a low-privileged actor in the non-secure world can corrupt or leak secure-world memory. In enterprise reality, though, this is already-post-compromise, local-only, Arm/OP-TEE-specific, and feature-gated to Secure Partition deployments; that combination is enough downward pressure to drop it into MEDIUM for patch prioritization across a large fleet.
4 steps from start to impact.
Land code on the normal-world side
- Attacker has local code execution in the REE/normal world
- Target is an Arm device using OP-TEE
- This is not remotely reachable from the internet by itself
- A lot of enterprise assets do not run OP-TEE at all
Reach the FF-A SPMC path with a custom caller
sp_mem_remove(), sp_mem_is_shared(), or sp_mem_get_receiver(). The advisory names the relevant FF-A operations: FFA_MEM_SHARE, FFA_MEM_LEND, FFA_MEM_RELINQUISH, and FFA_MEM_RECLAIM; in practice this means a custom userspace harness or existing FF-A/TEE plumbing, not an off-the-shelf mass-exploitation tool.- OP-TEE is configured as S-EL1 SPMC
CFG_SECURE_PARTITION=yis enabled- The platform actually uses FF-A Secure Partition flows
- This feature set is niche compared with mainstream OP-TEE deployments
- Many OP-TEE systems never enable Secure Partitions, so the vulnerable code path is absent
CFG_SECURE_PARTITION=y.Win the race in shared-memory teardown
receiver or region object. The advisory's included patch shows the root cause clearly: teardown freed list elements before the global synchronization fully serialized access.- Attacker can trigger concurrent FF-A memory operations
- Target has enough timing exposure under load to make the race practical
- Races are inherently less deterministic than straight-line bugs
- Platform scheduling and workload timing may make exploitation unreliable on some devices
Corrupt or leak secure-world state
struct sp_mem_map_region or struct sp_mem_receiver. The advisory states the impact as secure-world memory corruption and information leakage; in the worst case that undermines the trust boundary protecting Secure Partitions and whatever secrets or integrity guarantees they enforce.- Exploit reaches a valid dangling-pointer dereference path
- The corrupted/read-freed object produces useful side effects
- The advisory stops short of claiming turnkey code execution in the secure world
- Blast radius is device-local rather than enterprise-wide unless the vulnerable platform is broadly deployed
The supporting signals.
| In-the-wild status | No active exploitation evidence located in the sources reviewed, and not listed in CISA KEV as of 2026-06-03. |
|---|---|
| Public PoC status | No standalone public exploit repo found. The GitHub advisory includes a detailed root-cause writeup and patch diff, which is enough for a capable researcher to build a harness, but it is not point-and-shoot commodity tradecraft. |
| EPSS | No indexed EPSS value was surfaced in the searched sources on 2026-06-03. Check the FIRST EPSS API directly for the current score once the CVE is fully indexed there. |
| KEV status | Not KEV-listed. CISA's KEV catalog is the right source of truth here, and this CVE was not present in the reviewed catalog source. |
| CVSS vector | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — that is a local, low-privilege, no-user-interaction bug with high impact *after* the attacker is already on the box. |
| Affected scope | Per the GitHub advisory: >= 3.16.0 for package S-EL1 SPMC for S-EL0 SPs (OP-TEE), but only when CFG_SECURE_PARTITION=y. |
| Fixed versions | Vendor fix is 4.11 and later. I found no authoritative distro backport matrix in the reviewed sources, so assume firmware/vendor BSP backports must be checked per device supplier. |
| Exposure reality | Shodan/Censys/FOFA-style internet exposure data is mostly irrelevant here. This is not a remotely exposed application service; it is a firmware/TEE boundary bug reachable from local normal-world code on affected Arm platforms. |
| Disclosure timeline | There are two dates to keep straight: the GitHub advisory was published on 2026-05-25, while your intel block says CVE disclosure on 2026-06-03. Treat 2026-05-25 as the first public technical advisory date. |
| Reporter / maintainer | The advisory was published by Jens Wiklander in the OP-TEE/optee_os GitHub Security Advisory workflow. |
noisgate verdict.
The decisive factor is deployment narrowing: this bug only matters when OP-TEE is running as an S-EL1 SPMC with Secure Partitions enabled, which is far from universal even across OP-TEE users. On top of that, exploitation is local/post-compromise, so this is usually a second-stage trust-boundary break, not an initial-access event.
Why this verdict
- Vendor baseline starts at 7.8 HIGH because secure-world memory corruption is serious on an affected device.
- Downward adjustment: requires attacker presence in the normal world.
AV:L/PR:Lmeans this is already past initial access; you're dealing with a post-compromise escalation or boundary-crossing step, not a front-door exploit. - Downward adjustment: feature-gated to
CFG_SECURE_PARTITION=y. A large fraction of OP-TEE deployments will never expose the vulnerable SPMC/S-EL0 SP path at all. - Downward adjustment: niche platform population. This is Arm TEE firmware territory, not a broadly internet-exposed enterprise middleware tier.
- Upward adjustment retained: secure-world blast radius on affected devices. If you do run this configuration, corruption or leakage in the secure world is strategically important because it cuts across the trust boundary the platform is supposed to enforce.
Why not higher?
It is not higher because the attack path compounds three major friction points: local foothold required, specific OP-TEE role required, and Secure Partition feature enabled. That combination sharply limits both attacker reach and the proportion of enterprise assets that are truly exploitable.
Why not lower?
It is not lower because on the subset of affected devices, the bug lives in the secure-world memory-sharing path, not a harmless userspace corner case. Even without public exploitation, breaking or reading secure-world state can invalidate hardware-backed trust assumptions, so this deserves more than backlog-only treatment.
What to do — in priority order.
- Inventory Secure Partition deployments — Identify which Arm platforms actually run OP-TEE as S-EL1 SPMC with
CFG_SECURE_PARTITION=y. For a MEDIUM verdict there is no noisgate mitigation SLA, so do this in the normal remediation workflow while tracking toward the 365-day remediation window. - Constrain local code execution on affected devices — Harden the normal-world side because the bug is only reachable after local code execution. Reduce shell access, lock down service accounts, and minimize who can run arbitrary binaries on affected systems; for MEDIUM, there is no mitigation SLA, so align this with standard hardening work rather than emergency change control.
- Prefer vendor BSP or firmware bundles over ad-hoc source swaps — Most enterprises consume OP-TEE through a silicon vendor or device OEM BSP, not from upstream source directly. Validate whether your board vendor has backported the
sp_mem_remove()fix or rolled OP-TEE 4.11+ into a signed firmware package, and complete that within the 365-day remediation window. - Monitor TEE crash and reboot artifacts — On devices you cannot remediate quickly, collect watchdog resets, secure-world panic messages, and anomalous TEE/FF-A errors from kernel logs and telemetry. This will not stop exploitation, but it gives you a shot at spotting unstable exploit attempts during the normal remediation cycle.
- WAFs and perimeter IPS do nothing here because the vulnerable boundary is not an internet-facing HTTP service.
- External attack-surface scans will not tell you whether
CFG_SECURE_PARTITION=yis enabled inside firmware. - MFA helps with admin access but does not materially change the exploit mechanics once an attacker already has local code execution.
- Generic EDR alone may see a userland process, but it usually cannot reason about OP-TEE build flags or prove the secure-world code path is present.
Crowdsourced verification payload.
Run this on the target Arm/Linux device or on a mounted firmware filesystem from your build/forensics workstation. Invoke it as sudo bash ./check_optee_cve_2026_40290.sh because reading /boot, firmware blobs, and some package metadata may require root; it returns VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env bash
# check_optee_cve_2026_40290.sh
# Best-effort exposure check for CVE-2026-40290
# Logic:
# - Vulnerable if OP-TEE version is >= 3.16.0 and < 4.11.0
# - AND Secure Partition support appears enabled/configured
# - Otherwise PATCHED if version >= 4.11.0
# - UNKNOWN if evidence is incomplete
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
set -u
found_version=""
secure_partition="unknown"
ver_ge() {
[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | tail -n1)" = "$1" ]
}
ver_lt() {
[ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
note() {
printf '%s\n' "$*" >&2
}
extract_version_from_file() {
local f="$1"
[ -r "$f" ] || return 1
grep -Eao '([0-9]+\.[0-9]+(\.[0-9]+)?)' "$f" 2>/dev/null | head -n1
}
# 1) Try common package managers / metadata
for cmd in optee_os optee-version; do
if command -v "$cmd" >/dev/null 2>&1; then
v="$($cmd --version 2>/dev/null | grep -Eao '([0-9]+\.[0-9]+(\.[0-9]+)?)' | head -n1)"
if [ -n "$v" ]; then
found_version="$v"
note "Found version via $cmd: $found_version"
break
fi
fi
done
if [ -z "$found_version" ] && command -v dpkg-query >/dev/null 2>&1; then
v="$(dpkg-query -W -f='${Version}\n' optee-os 2>/dev/null | grep -Eao '([0-9]+\.[0-9]+(\.[0-9]+)?)' | head -n1)"
if [ -n "$v" ]; then
found_version="$v"
note "Found version via dpkg: $found_version"
fi
fi
if [ -z "$found_version" ] && command -v rpm >/dev/null 2>&1; then
v="$(rpm -q --qf '%{VERSION}\n' optee-os 2>/dev/null | grep -Eao '([0-9]+\.[0-9]+(\.[0-9]+)?)' | head -n1)"
if [ -n "$v" ]; then
found_version="$v"
note "Found version via rpm: $found_version"
fi
fi
# 2) Try common files / firmware blobs
if [ -z "$found_version" ]; then
for f in \
/etc/optee/version \
/usr/share/optee/version \
/sys/firmware/devicetree/base/firmware/optee/version \
/boot/tee.bin \
/boot/optee.bin \
/boot/tee-header_v2.bin \
/lib/firmware/tee.bin \
/lib/firmware/optee.bin; do
v="$(extract_version_from_file "$f")"
if [ -n "$v" ]; then
found_version="$v"
note "Found version via file $f: $found_version"
break
fi
done
fi
# 3) Try strings on blobs if present
if [ -z "$found_version" ] && command -v strings >/dev/null 2>&1; then
for f in /boot/*.bin /lib/firmware/*.bin; do
[ -e "$f" ] || continue
v="$(strings "$f" 2>/dev/null | grep -Eao 'OP-TEE[^0-9]*([0-9]+\.[0-9]+(\.[0-9]+)?)' | grep -Eao '([0-9]+\.[0-9]+(\.[0-9]+)?)' | head -n1)"
if [ -n "$v" ]; then
found_version="$v"
note "Found version via strings on $f: $found_version"
break
fi
done
fi
# Detect CFG_SECURE_PARTITION=y from likely build/config artifacts
for f in \
/etc/optee/conf.mk \
/usr/share/optee/conf.mk \
/boot/conf.mk \
/boot/optee.conf \
./conf.mk \
./out/conf.mk \
./out/arm-plat-*/conf.mk \
./core/arch/arm/plat-*/conf.mk; do
# shellcheck disable=SC2086
for realf in $f; do
[ -r "$realf" ] || continue
if grep -Eq '^\s*CFG_SECURE_PARTITION\s*=\s*y\s*$' "$realf" 2>/dev/null; then
secure_partition="enabled"
note "Detected CFG_SECURE_PARTITION=y in $realf"
break 2
fi
if grep -Eq '^\s*CFG_SECURE_PARTITION\s*=\s*n\s*$' "$realf" 2>/dev/null; then
secure_partition="disabled"
note "Detected CFG_SECURE_PARTITION=n in $realf"
fi
done
done
# Heuristic fallback: SPMC docs/manifests / filenames may indicate Secure Partition support
if [ "$secure_partition" = "unknown" ]; then
for f in /boot/*spmc* /boot/*secure*partition* ./out/*spmc* ./out/*secure*partition*; do
[ -e "$f" ] || continue
secure_partition="enabled"
note "Heuristic hit for Secure Partition/SPMC artifact: $f"
break
done
fi
# Decision
if [ -n "$found_version" ]; then
if ver_ge "$found_version" "4.11.0"; then
echo "PATCHED"
exit 0
fi
if ver_ge "$found_version" "3.16.0" && ver_lt "$found_version" "4.11.0"; then
if [ "$secure_partition" = "enabled" ]; then
echo "VULNERABLE"
exit 1
elif [ "$secure_partition" = "disabled" ]; then
echo "PATCHED"
note "Installed version is in affected range, but CFG_SECURE_PARTITION appears disabled."
exit 0
else
echo "UNKNOWN"
note "Version is in affected range, but Secure Partition enablement could not be determined."
exit 2
fi
fi
fi
echo "UNKNOWN"
if [ -z "$found_version" ]; then
note "Could not determine OP-TEE version from package metadata or firmware files."
fi
if [ "$secure_partition" = "unknown" ]; then
note "Could not determine whether CFG_SECURE_PARTITION is enabled."
fi
exit 2
If you remember one thing.
CFG_SECURE_PARTITION=y; for a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, and the noisgate remediation SLA is therefore ≤ 365 days. In practice: identify the affected subset now, confirm whether your OEM/BSP already carries the upstream fix, and schedule firmware remediation in the normal annual cycle ahead of lower-value backlog items but behind remotely reachable or KEV-listed issues.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.