Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
CRITICAL severity

CVE-2026-40576 excel-mcp-server

CRITICALFix: haris-musa/excel-mcp-server@f51340e

CVE-2026-40576 is a critical-severity (CVSS 9.4) Path Traversal vulnerability in excel-mcp-server. A fix is available for excel-mcp-server — see the affected versions and patch details below.

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') in excel-mcp-server

Also known asGHSA-j98m-w3xp-9f56PYSEC-2026-331
Published
Apr 21, 2026
Updated
Aug 12, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 21, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-40576.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs33th percentile — riskier than 33% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-40576 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,333 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐍excel-mcp-server

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

A path traversal vulnerability exists in excel-mcp-server versions up to and including 0.1.7. When running in SSE or Streamable-HTTP transport mode (the documented way to use this server remotely), an unauthenticated attacker on the network can read, write, and overwrite arbitrary files on the host filesystem by supplying crafted filepath arguments to any of the 25 exposed MCP tool handlers.

The server is intended to confine file operations to a directory set by the EXCEL_FILES_PATH environment variable. The function responsible for enforcing this boundary — get_excel_path() — fails to do so due to two independent flaws: it passes absolute paths through without any check, and it joins relative paths without resolving or validating the result. Combined with zero authentication on the default network-facing transport and a default bind address of 0.0.0.0 (all interfaces), this allows trivial remote exploitation.


Details

FieldValue
Packageexcel-mcp-server (PyPI)
Repositoryhttps://github.com/haris-musa/excel-mcp-server
Affected versions<= 0.1.7
Tested version0.1.7 — commit de4dc75
CWECWE-22 — Improper Limitation of a Pathname to a Restricted Directory
CVSS 3.18.2 HighAV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H
Transports affectedsse, streamable-http (network-facing)
Authentication requiredNone

Vulnerable Code

The root cause is in src/excel_mcp/server.py, lines 75–94:

def get_excel_path(filename: str) -> str:
    """Get full path to Excel file."""

    # FLAW 1 — absolute paths bypass the sandbox entirely
    if os.path.isabs(filename):
        return filename                     # line 86: returned as-is

    # In SSE/HTTP mode, EXCEL_FILES_PATH is set
    if EXCEL_FILES_PATH is None:
        raise ValueError(...)

    # FLAW 2 — relative paths joined without boundary validation
    return os.path.join(EXCEL_FILES_PATH, filename)   # line 94: "../" escapes

Why this is exploitable

Flaw 1 — Absolute path bypass (line 86): If the attacker passes filepath="/etc/shadow" or filepath="/home/user/secrets.xlsx", the function returns it unchanged. The sandbox directory EXCEL_FILES_PATH is never consulted.

Flaw 2 — Relative traversal (line 94): os.path.join("/srv/sandbox", "../../etc/passwd") produces "/srv/sandbox/../../etc/passwd", which resolves to "/etc/passwd". No os.path.realpath() or os.path.commonpath() check is performed, so ../ sequences escape the sandbox.

Contributing factors that increase severity

  1. Default bind address is 0.0.0.0 (all interfaces) — server.py line 70:

    host=os.environ.get("FASTMCP_HOST", "0.0.0.0"),
    

    A user who follows the README and runs uvx excel-mcp-server streamable-http without explicitly setting FASTMCP_HOST exposes the server to their entire LAN.

  2. Zero authentication — FastMCP's SSE and Streamable-HTTP transports ship with no authentication. The server adds none. Any TCP client that reaches port 8017 can call any tool.

  3. All 25 tool handlers are affected — every @mcp.tool() decorated function calls get_excel_path(filepath) as its first action. This is not an isolated endpoint; it is the entire API surface.

  4. Arbitrary directory creationsrc/excel_mcp/workbook.py line 24 runs path.parent.mkdir(parents=True, exist_ok=True) before saving, meaning the attacker can create directory trees at any writable location.


Proof of Concept

Video demonstration

asciicast

asciinema recording: https://asciinema.org/a/2HVA3uKvVeFahIXY

I have also attached the full PoC shell script (record-poc.sh) and the Python exploit script (exploit_test.py) to a Google Drive for the maintainer to review and reproduce independently:

Google Drive (PoC scripts): Shared privately via email

Contents:

  • record-poc.sh — automated PoC recording script (bash)
  • exploit_test.py — Python exploit that tests all 7 primitives against a running server

Setup

# install
pip install excel-mcp-server mcp httpx

# start server with a sandbox directory
mkdir -p /tmp/sandbox
EXCEL_FILES_PATH=/tmp/sandbox FASTMCP_HOST=127.0.0.1 FASTMCP_PORT=8017 \
    excel-mcp-server streamable-http

Exploit script

The following Python script connects to the server with zero credentials and demonstrates all exploitation primitives:

{REMOVING CAUSE FOR SAFETY CONCERNS}

Results

All 7 test cases passed against a live server instance:

CONFIRMED: 7  |  FAILED: 0

[CONFIRMED] AUTH: Connected with ZERO authentication. 25 tools exposed.
[CONFIRMED] P1-WRITE-ABS: file exists=True size=4783B (outside sandbox)
[CONFIRMED] P2-WRITE-TRAVERSAL: escaped sandbox via ../ exists=True
[CONFIRMED] P3-MKDIR: attacker directory tree created=True
[CONFIRMED] P4-READ: exfiltrated SSN=True name=True
[CONFIRMED] P5-OVERWRITE: victim data replaced=True
[CONFIRMED] P6-STAT: server attempted to open /etc/hostname (format error confirms file access)

Filesystem evidence (independently verified after exploit)

Files created outside the sandbox:

$ ls -la /tmp/cve-hunt/outside_sandbox/
-rw-rw-r-- 1 hitarth hitarth 4783 Apr 10 17:36 P1_absolute_write.xlsx
-rw-rw-r-- 1 hitarth hitarth 4783 Apr 10 17:36 P2_traversal_write.xlsx

Attacker-created directory tree:

$ find /tmp/cve-hunt/attacker_dir
/tmp/cve-hunt/attacker_dir
/tmp/cve-hunt/attacker_dir/deep
/tmp/cve-hunt/attacker_dir/deep/nested
/tmp/cve-hunt/attacker_dir/deep/nested/x.xlsx

Victim file after overwrite (original SSN destroyed):

  ('SSN', 'Name')
  ('ATTACKER-CONTROLLED', 'PWNED')     # was: ('123-45-6789', 'Alice Johnson')
  ('987-65-4321', 'Bob Smith')

Impact

An unauthenticated network attacker can:

WhatHowSeverity
Read any .xlsx file on the hostSupply absolute path to read_data_from_excelConfidentiality loss — cross-tenant data theft of financial data, HR records, reports
Write .xlsx files anywhere on the filesystemSupply absolute path or ../ traversal to create_workbook or write_data_to_excelIntegrity loss — destroy or corrupt any writable .xlsx, plant malicious files
Create arbitrary directories anywhere writablecreate_workbook triggers mkdir(parents=True) on attacker-controlled pathPrecursor to privilege escalation or DoS
Overwrite existing business files with attacker contentwrite_data_to_excel with absolute path to targetSilent data corruption — audit reports, salary sheets, financial models
Fill disk via repeated writesLoop create_workbook with unique filenamesDenial of service — crash services dependent on free disk
Plant macro-enabled templates (.xltm) at known shared pathscreate_workbook at path like /home/user/Templates/report.xltmClient-side RCE chain when downstream user opens the template in Excel

Who is affected

Anyone running excel-mcp-server in SSE or Streamable-HTTP mode on a reachable network — which is the documented and recommended deployment for remote use. The project README explicitly states:

  • "Works both locally and as a remote service"
  • "Streamable HTTP Transport (Recommended for remote connections)"

The server has 3,655+ GitHub stars and is published on PyPI with active downloads.


Suggested Fix

Replace get_excel_path() with a version that enforces the sandbox boundary:

import os

def get_excel_path(filename: str) -> str:
    if EXCEL_FILES_PATH is None:
        # stdio mode: local caller is trusted
        if not os.path.isabs(filename):
            raise ValueError("must be absolute path in stdio mode")
        return filename

    # Remote mode (SSE / streamable-http): enforce sandbox
    if os.path.isabs(filename):
        raise ValueError("absolute paths are not permitted in remote mode")
    if "\x00" in filename:
        raise ValueError("NUL byte in filename")

    base = os.path.realpath(EXCEL_FILES_PATH)
    candidate = os.path.realpath(os.path.join(base, filename))

    if not candidate.startswith(base + os.sep) and candidate != base:
        raise ValueError(f"path escapes EXCEL_FILES_PATH: {filename}")

    return candidate

References

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIexcel-mcp-serverall versions0.1.8pip install --upgrade 'excel-mcp-server==0.1.8'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for excel-mcp-server, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update excel-mcp-server to 0.1.8 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-40576 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-40576 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-40576. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary A path traversal vulnerability exists in [`excel-mcp-server`](https://github.com/haris-musa/excel-mcp-server) versions up to and including `0.1.7`. When running in SSE or Streamable-HTTP transport mode (the documented way to use this server remotely), an unauthenticated attacker on the network can read, write, and overwrite arbitrary files on the host filesystem by supplying crafted `filepath` arguments to any of the 25 exposed MCP tool handlers. The server is intended to confine file operations to a directory set by the `EXCEL_FILES_PATH` environment variable. The function respon
O3 Security · Impact-Aware SCA

Is CVE-2026-40576 in your dependencies?

O3 Security finds CVE-2026-40576 across PyPI dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-40576: excel-mcp RCE (Critical 9.4) | O3 Security