This is a bad lock on an office desk drawer, not an open loading dock
CVE-2026-12221 is a stack-based buffer overflow in the Yealink SIP-T46U firmware upgrade handler at /api/upgrade/upgrade, triggered by crafted uid or start_offset input to sprintf. Public reporting currently ties the issue to firmware 108.86.0.118 specifically, not a broad T4U family range. The attack path is not internet-native; public descriptions say it must be launched from the local/adjacent network, and the phone web interface is typically reachable only from the same network segment or voice VLAN.
The vendor-style HIGH/8.0 baseline overstates enterprise urgency because it prices the memory corruption heavily but underprices the reachability friction. In the real world, an attacker usually needs to already be on the voice network and have at least low-privileged access to the phone's admin surface; that means this is more of a post-compromise amplifier against a handset than a fleet-opening edge bug.
4 steps from start to impact.
Get onto the phone's network
nmap or browser access to the phone IP; the important part is not the tool but the position. This prerequisite already implies the attacker is inside the site, on a bridged segment, or abusing poor VLAN separation.- Access to the same local network or voice VLAN as the phone
- IP reachability to the handset web interface
- Most enterprises do not expose desk phone web UIs directly to the internet
- Voice VLANs are often ACL'd away from user subnets and guest networks
- Some deployments disable the phone web server entirely
Reach the authenticated upgrade surface
curl with existing credentials; public support docs show factory defaults of admin/admin, but many managed deployments rotate them during provisioning. If the web server is disabled or credentials were changed, the chain stalls here.- Phone web server enabled over HTTP or HTTPS
- Low-privileged access to the interface, matching the reported
PR:Lcondition
- Provisioned phones often have changed admin passwords
- Some carriers and admins disable web administration after deployment
- Same-network access is still required even with valid credentials
Send crafted upgrade request with the PoC
/api/upgrade/upgrade targeting uid/start_offset. The likely operator tool is a custom HTTP PoC referenced by VulDB/cvefeed, not a mainstream framework. This step can plausibly crash the process or corrupt memory; reliable code-exec quality is not demonstrated in the public sources I reviewed.- Access to the upgrade endpoint
- Ability to submit crafted POST parameters
- Public reporting proves exploitability but not mature weaponization
- Memory corruption on embedded devices is often unstable across builds
- No source reviewed showed broad in-the-wild exploitation or turnkey mass-scanning
/api/upgrade/upgrade, repeated failed firmware-upload attempts, and handset reboots/crashes. Detection is mostly network telemetry or admin-plane logging, not endpoint tooling.Land impact on the handset
- Successful memory corruption in the embedded web process
- Useful post-crash or post-exploitation foothold on the device
- Blast radius is usually one handset or one extension
- Desk phones are not canonical high-value control-plane assets
- Operational value is situational unless the phone belongs to a sensitive user or call flow
admin/admin exposure and store the new credentials in your voice-management vault. This directly attacks the PR:L prerequisite; for a MEDIUM verdict there is no mitigation SLA, so complete it during standard credential hygiene work.- A perimeter WAF does not help if the vulnerable web UI is only reachable on an internal voice subnet; the traffic never hits your internet edge.
- MFA on the PBX or SSO portal does not protect the handset's own local admin interface.
- Patching only the PBX is not a fix; the vulnerable code lives on the phone firmware.
- EDR on user workstations does not see inside the embedded Yealink handset process where the overflow occurs.
The supporting signals.
| In-the-wild status | No active exploitation evidence found in the sources reviewed; not present in CISA KEV as checked against the KEV catalog page. |
|---|---|
| PoC availability | Public PoC/exploit claimed available by VulDB and mirrored in cvefeed. I did not independently validate the payload. |
| EPSS | 0.00371 from your intel block — low predicted near-term exploitation probability; percentile was not available in the sources checked. |
| KEV status | Not KEV-listed as of the catalog page checked. No due date or federal emergency signal. |
| CVSS vector | CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — the important limiter is AV:A + PR:L: adjacent-network plus low privileges, not unauthenticated internet RCE. |
| Affected versions | Public reporting ties the bug to Yealink SIP-T46U firmware 108.86.0.118. I found no authoritative vendor advisory expanding that into a broader affected range. |
| Fixed versions | I found no vendor security advisory mapping a fix to CVE-2026-12221. Yealink's 3CX resource page lists a newer T46U firmware 108.87.0.22, but that is not the same as a confirmed CVE fix statement. |
| Exposure reality | This is usually an internal management-plane issue. Support docs for the T46U say the web UI is accessed from a device on the same network and can be disabled, which sharply reduces mass exploit reach compared with edge appliances. |
| Disclosure | 2026-06-15 per the CVE publication trail; VulDB timeline shows public advisory activity on 2026-06-14. |
| Researcher / source | Public attribution in VulDB points to submitter CookedMelon; vendor response is described there as no response. |
Sources.
- VulDB entry for CVE-2026-12221
- cvefeed summary and reference trail
- Yealink T46U configuration manual (web UI login defaults)
- Telebroad T46U web UI access article (same-network access, web server enable/disable)
- Yealink 3CX resource page listing newer T46U firmware
- Yealink T46U product technical specs
- FIRST EPSS project
- CISA Known Exploited Vulnerabilities catalog
Why this verdict
- Baseline starts high: memory corruption in upgrade code with C/I/A impact on a widely deployed handset deserves respect; I started from the vendor's 8.0 HIGH rather than hand-waving it away.
- Reachability penalty:
AV:Ameans the attacker needs same-network/adjacent access. In enterprise terms that usually means the voice VLAN, a bridged LAN segment, or another already-compromised internal foothold. That is a major downward adjustment because it assumes a prior stage of compromise or unusually weak segmentation. - Auth penalty:
PR:Lmeans the exploit path is not anonymous spray-and-pray. T46U admin docs and support material show a managed web interface for firmware actions; if the org rotated passwords or disabled the web server, the reachable population drops again. - Exposure penalty: desk phones are commonly internal-only assets. Public support guidance explicitly describes same-network web access and optional web-server disablement, which is the opposite of an internet-edge blast radius.
- Detection/weaponization penalty: a public PoC exists, but I found no KEV listing, no campaign reporting, and no evidence of turnkey mass exploitation. That keeps this out of HIGH despite the underlying bug class.
- Role multiplier: low-value role — on a standard desk phone, the chain succeeds only to the handset/extension context; realistic blast radius is host or single extension, not tenant or fleet.
- Role multiplier: typical role — on a normal office T46U in a voice VLAN, the chain can still succeed, but blast radius remains phone + SIP identity unless you already have additional PBX/admin weaknesses to chain with it.
- Role multiplier: high-value role — this product is not a canonical high-value control-plane component like an IdP, hypervisor, backup server, or edge firewall. Even on an executive or receptionist handset, the documented chain still lands on the phone, so there is no verdict floor forcing HIGH.
Why not higher?
It is not higher because the path is neither unauthenticated internet-facing nor clearly tied to active exploitation. Just as important, the affected component is a desk phone, not an identity, backup, hypervisor, PKI, or network-edge role where one successful exploit routinely becomes fleet compromise.
Why not lower?
It is not lower because this is still memory corruption in firmware administration code with a public PoC claim and high theoretical impact on the target device. If your voice VLAN is flat, if web admin is left enabled, or if default credentials survived provisioning, the practical friction shrinks fast.
Crowdsourced verification payload.
Run this from an auditor workstation or jump host on the same LAN/voice VLAN as the phone. Invoke it as ./check_t46u_cve_2026_12221.sh https://192.168.1.22 admin admin; it needs network reachability to the handset web UI and works best with valid handset credentials, but it will still try unauthenticated fetches and return UNKNOWN if it cannot prove the firmware build.
#!/usr/bin/env bash
# check_t46u_cve_2026_12221.sh
# Purpose: best-effort check for Yealink SIP-T46U firmware build associated with CVE-2026-12221.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 1=vulnerable, 0=patched, 2=unknown, 3=usage/network error
set -u
TARGET="${1:-}"
USER="${2:-}"
PASS="${3:-}"
if [[ -z "$TARGET" ]]; then
echo "Usage: $0 <http[s]://phone-ip> [username] [password]" >&2
exit 3
fi
if ! command -v curl >/dev/null 2>&1; then
echo "UNKNOWN - curl not installed" >&2
exit 2
fi
AUTH=()
if [[ -n "$USER" || -n "$PASS" ]]; then
AUTH=(--user "$USER:$PASS")
fi
fetch() {
local url="$1"
curl -ksS --connect-timeout 5 --max-time 10 "${AUTH[@]}" "$url" 2>/dev/null || true
}
BASE="${TARGET%/}"
DATA=""
DATA+="$(fetch "$BASE/")"
DATA+=$'\n'
DATA+="$(fetch "$BASE/servlet?m=mod_data&p=status&q=load")"
DATA+=$'\n'
DATA+="$(fetch "$BASE/cgi-bin/cgiServer.exx?action=getInfo")"
if [[ -z "$DATA" ]]; then
echo "UNKNOWN - no HTTP response from target"
exit 2
fi
# Normalize whitespace for easier matching.
DATA="$(printf '%s' "$DATA" | tr '\r' '\n')"
# Exact build publicly associated with CVE-2026-12221.
if printf '%s' "$DATA" | grep -Eq '\b108\.86\.0\.118\b'; then
echo "VULNERABLE - detected firmware 108.86.0.118"
exit 1
fi
# Best-effort newer-train check. Public sources show 108.87.0.22 exists,
# but no authoritative vendor advisory was found explicitly mapping that build
# to this CVE. Treat as PATCHED only in the narrow sense of 'not the known affected build'.
if printf '%s' "$DATA" | grep -Eq '\b108\.87\.[0-9]+\.[0-9]+\b'; then
VER="$(printf '%s' "$DATA" | grep -Eo '\b108\.87\.[0-9]+\.[0-9]+\b' | head -n1)"
echo "PATCHED - detected newer firmware train $VER (not the known affected build 108.86.0.118)"
exit 0
fi
# Generic Yealink build extraction for operator context.
VER_ANY="$(printf '%s' "$DATA" | grep -Eo '\b[0-9]{2,3}\.[0-9]{2}\.[0-9]\.[0-9]{1,3}\b' | head -n1 || true)"
if [[ -n "$VER_ANY" ]]; then
echo "UNKNOWN - detected firmware $VER_ANY, but could not map it confidently to CVE-2026-12221"
exit 2
fi
echo "UNKNOWN - could not determine firmware version from handset web responses"
exit 2