← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-41101 · CWE-284 · Disclosed 2026-05-12

Improper access control in Microsoft Office Word

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

This is a forged badge inside the building, not a broken front door

CVE-2026-41101 is an improper access control flaw in Microsoft Word for Android that Microsoft classifies as a spoofing issue. Public metadata is thin, but the authoritative records point to Word for Android versions before 16.0.19822.20190 as affected, with the fixed build at 16.0.19822.20190. The attacker must already have local access and low privileges on the same Android device, and Microsoft says no user interaction is required once that foothold exists.

Microsoft's 7.1 HIGH score is defensible in pure CVSS math, but it overstates enterprise urgency. This is not remotely reachable, not unauthenticated, not a server-side trust boundary break, and not an RCE. In real fleets this behaves like a post-compromise mobile client abuse case with per-device blast radius, so the right operational bucket is LOW unless you have a very large Android M365 estate handling sensitive approvals or regulated document workflows.

"High on paper, low in the field: this needs a local foothold on the Android device first."
02 · The Attack Path

3 steps from start to impact.

STEP 01

Land on the Android device with ADB or a malicious app

The attacker first needs a foothold on the same Android handset or work profile running vulnerable Word. In practice that means prior compromise, physical access, abuse of debugging access, or a malicious app already installed under the user's context.
Conditions required:
  • Attacker has local access to the target Android device
  • A vulnerable Word for Android build is installed
  • Attacker can execute code or interact within the same device profile
Where this breaks in practice:
  • This is already post-initial-access
  • MDM, Play Protect, app allow-listing, and blocked sideloading cut down the reachable population
  • Corporate Android adoption is usually a subset of the total Office estate
Detection/coverage: Traditional vuln scanners rarely see this well; you need MDM/EMM or mobile inventory with package/version visibility.
STEP 02

Abuse the Word access control bug to spoof trusted state

With that foothold, the attacker abuses the improper access control condition inside Word for Android to create or present a spoofed state. Public disclosure does not describe the exact primitive, but the impact category suggests impersonated content, trust signals, or document/account context rather than code execution.
Conditions required:
  • Local authenticated context on the device
  • Word for Android before 16.0.19822.20190
Where this breaks in practice:
  • No public proof-of-concept was found
  • Microsoft did not publish deep technical details
  • Application sandboxing and work-profile separation can limit adjacent data access
Detection/coverage: Signature-based coverage is weak because the issue is client-side and the abuse pattern is application-behavioral, not network-distinctive.
STEP 03

Leverage the spoofed view to mislead the user or tamper with trusted content

The practical outcome is likely document trust abuse: misleading a user, falsifying visible state, or manipulating content under a trusted app surface. That can matter in approval workflows or sensitive mobile document handling, but the impact is normally bounded to the device, the signed-in account, and whatever files or views Word can already reach.
Conditions required:
  • Target user relies on Word mobile for business documents
  • Relevant files or account context are present on the device
Where this breaks in practice:
  • Blast radius is usually one device or one user session
  • Mobile Office use is often secondary to desktop workflows
  • MAM containerization and conditional access reduce downstream abuse
Detection/coverage: Look for suspicious mobile app posture, rooted devices, unusual document activity, and unmanaged Android installs rather than direct exploit artifacts.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public exploitation evidence found in the sources reviewed, and not listed in CISA KEV.
Public PoC availabilityNone found. GitHub Advisory shows "No known source code" for this CVE.
EPSS0.044% (14th percentile) per GitHub Advisory Database/FIRST-linked EPSS data.
KEV statusNot KEV-listed as of this assessment.
CVSS vectorCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N — the key down-pressure is AV:L + PR:L, meaning the attacker already has a foothold on the handset.
Affected versionsNVD maps the vulnerable Android package range as Word for Android before 16.0.19822.20190.
Fixed version16.0.19822.20190 or later; for managed fleets this should arrive through Google Play / Managed Google Play distribution.
Exposure and scanning realityInference: this is a client-side Android app, not an internet-facing service, so Shodan/Censys-style exposure counting is effectively N/A. Your real exposure source is MDM app inventory, not perimeter scanning.
Disclosure datePublished 2026-05-12 during Microsoft's May 2026 release cycle.
Researcher / reporterMicrosoft's public advisory and NVD entry reviewed here do not credit a reporting researcher or external organization.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.6/10)

The decisive factor is attacker position: this bug requires local authenticated access on the Android device, which means the attacker is already past your primary control plane. That sharply narrows both the exposed population and the blast radius compared with remotely reachable Office bugs.

HIGH Affected product/version range and vendor metadata
MEDIUM Operational impact assessment given sparse public technical detail

Why this verdict

  • Start from Microsoft's 7.1, then subtract for attacker position: AV:L/PR:L means the adversary already has a local foothold on the handset, which is classic post-compromise friction.
  • Not remotely reachable: this is an Android client app, not an internet-facing service, so the reachable population is your installed mobile Word base rather than every exposed host on the perimeter.
  • Spoofing, not code execution: even if exploitation is real, the likely outcome is trust abuse or document-context manipulation, not broad host takeover or wormable spread.
  • Weak exploitation signal: no KEV listing, no public exploitation evidence in reviewed sources, no public PoC located, and EPSS is very low at 0.044%.

Why not higher?

To justify MEDIUM or HIGH operationally, this would need either remote reachability, active exploitation, or a larger fleet-wide blast radius. Instead, the chain starts with prior local access on an Android device and ends in a spoofing outcome inside a single app context.

Why not lower?

It is not IGNORE because Microsoft shipped a fix, the vulnerable app is massively deployed in absolute terms, and once an attacker is on-device there may be meaningful trust and document-handling consequences. The absence of required user interaction after foothold also keeps it above pure paperwork.

05 · Compensating Control

What to do — in priority order.

  1. Force app auto-update — Use Managed Google Play or equivalent EMM controls to push Word for Android to 16.0.19822.20190+. For a LOW verdict there is no SLA (treat as backlog hygiene), so enforce this in the next normal mobile app maintenance cycle rather than breaking glass.
  2. Block sideloading and debug abuse — Disable unknown-source installs, restrict ADB/developer options where policy allows, and keep Play Protect enforced. This matters because the exploit chain already assumes local device access, and for LOW there is no SLA (treat as backlog hygiene).
  3. Use app protection and work profiles — Apply Intune/MAM controls so corporate data in Word stays containerized and conditional on device compliance. That limits what a local foothold can actually reach, and for LOW this is backlog hygiene with no formal deadline.
  4. Inventory vulnerable Android builds — Query MDM for the Word package and flag versions below 16.0.19822.20190. This is the only reliable enterprise exposure view because network scanners will not tell you much here; for LOW, do it through routine hygiene reporting.
What doesn't work
  • A WAF does not help because this is not a web-exposed server flaw.
  • Perimeter vulnerability scanning is weak here because the target is a mobile client app, not a listening service.
  • MFA alone does not fix a local app access-control bug once the attacker already has code or session access on the device.
06 · Verification

Crowdsourced verification payload.

Run this on an auditor workstation, CI job, or admin jump box against a CSV export from Intune/EMM/mobile inventory that includes app package/version data. Invoke it as python3 verify_cve_2026_41101.py mobile_apps.csv; no admin rights are required on the workstation, but you need permission to export device app inventory. Expected columns are flexible, but the script looks for a Word Android package/product plus a version such as 16.0.19822.20180.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# verify_cve_2026_41101.py
# Audit Microsoft Word for Android versions against CVE-2026-41101.
# Input: CSV export from MDM/EMM/app inventory.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/file error

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

FIXED_VERSION = (16, 0, 19822, 20190)
TARGET_PACKAGES = {
    'com.microsoft.office.word',
}
TARGET_NAME_HINTS = (
    'word for android',
    'microsoft word',
)


def parse_version(v: str) -> Optional[Tuple[int, ...]]:
    if not v:
        return None
    nums = re.findall(r'\d+', v)
    if not nums:
        return None
    return tuple(int(x) for x in nums)


def compare_versions(a: Tuple[int, ...], b: Tuple[int, ...]) -> int:
    max_len = max(len(a), len(b))
    a2 = a + (0,) * (max_len - len(a))
    b2 = b + (0,) * (max_len - len(b))
    if a2 < b2:
        return -1
    if a2 > b2:
        return 1
    return 0


def row_matches_word_android(row: dict) -> bool:
    hay = ' '.join(str(v or '').strip().lower() for v in row.values())
    if any(pkg in hay for pkg in TARGET_PACKAGES):
        return True
    return any(hint in hay for hint in TARGET_NAME_HINTS)


def get_version_from_row(row: dict) -> Optional[str]:
    preferred = [
        'version', 'app_version', 'application_version', 'package_version',
        'installed_version', 'version_name', 'build', 'app build'
    ]
    lowered = {str(k).strip().lower(): v for k, v in row.items()}
    for key in preferred:
        if key in lowered and str(lowered[key]).strip():
            return str(lowered[key]).strip()
    for k, v in lowered.items():
        if 'version' in k and str(v).strip():
            return str(v).strip()
    return None


def get_device_name(row: dict) -> str:
    preferred = ['device', 'device_name', 'managed_device_name', 'hostname', 'serial', 'user']
    lowered = {str(k).strip().lower(): v for k, v in row.items()}
    for key in preferred:
        if key in lowered and str(lowered[key]).strip():
            return str(lowered[key]).strip()
    return 'unknown-device'


def main() -> int:
    if len(sys.argv) != 2:
        print('UNKNOWN - usage: python3 verify_cve_2026_41101.py <inventory.csv>')
        return 3

    path = sys.argv[1]
    try:
        with open(path, newline='', encoding='utf-8-sig') as f:
            reader = csv.DictReader(f)
            if not reader.fieldnames:
                print('UNKNOWN - CSV has no header row')
                return 2

            matched = 0
            vulnerable = []
            patched = []
            unknown = []

            for row in reader:
                if not row_matches_word_android(row):
                    continue
                matched += 1
                device = get_device_name(row)
                version_str = get_version_from_row(row)
                parsed = parse_version(version_str or '')
                if not parsed:
                    unknown.append((device, version_str or ''))
                    continue
                if compare_versions(parsed, FIXED_VERSION) < 0:
                    vulnerable.append((device, version_str))
                else:
                    patched.append((device, version_str))

    except FileNotFoundError:
        print(f'UNKNOWN - file not found: {path}')
        return 3
    except Exception as e:
        print(f'UNKNOWN - failed to parse CSV: {e}')
        return 2

    if matched == 0:
        print('UNKNOWN - no Microsoft Word for Android entries found in inventory')
        return 2

    fixed_str = '.'.join(str(x) for x in FIXED_VERSION)
    print(f'Checked {matched} Word for Android record(s); fixed version is {fixed_str}')

    if vulnerable:
        print('VULNERABLE')
        for device, version in vulnerable[:25]:
            print(f'  {device}: {version}')
        if len(vulnerable) > 25:
            print(f'  ... and {len(vulnerable) - 25} more vulnerable record(s)')
        if unknown:
            print(f'  Note: {len(unknown)} matching record(s) had unknown version data')
        return 1

    if patched and not unknown:
        print('PATCHED')
        for device, version in patched[:10]:
            print(f'  {device}: {version}')
        if len(patched) > 10:
            print(f'  ... and {len(patched) - 10} more patched record(s)')
        return 0

    print('UNKNOWN')
    if patched:
        print(f'  {len(patched)} matching record(s) are at or above {fixed_str}')
    if unknown:
        print(f'  {len(unknown)} matching record(s) are missing usable version data')
        for device, version in unknown[:10]:
            display = version if version else '<empty>'
            print(f'  {device}: {display}')
    return 2


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

If you remember one thing.

TL;DR
Monday morning, do not treat this like a perimeter emergency: pull your MDM inventory for Word for Android < 16.0.19822.20190, confirm Managed Google Play auto-update is working, and roll fixes into the next normal mobile app hygiene cycle. For a LOW verdict, the noisgate mitigation SLA has no SLA (treat as backlog hygiene), and the noisgate remediation SLA likewise does not impose a formal deadline beyond backlog hygiene, so document the downgrade rationale and patch through standard mobile operations rather than emergency change control.

Sources

  1. Microsoft Security Update Guide - CVE-2026-41101
  2. NVD - CVE-2026-41101
  3. GitHub Advisory Database - GHSA-6449-fjcw-2pg6
  4. Google Play - Microsoft Word: Edit Documents
  5. Microsoft Intune - Add and Assign Managed Google Play Apps to Android Enterprise Devices
  6. Microsoft Support - May 2026 updates for Microsoft Office
  7. Trend Micro - May 2026 Microsoft CVE review table
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.