BACK TO SEARCH
amercat37/mealie-mcp-servercritical
MCP server for Mealie recipe manager with Authentik OAuth support
This MCP server provides AI assistants with access to a Mealie recipe management system, enabling recipe search, creation, editing, meal planning, sho...
purpose: This MCP server provides AI assistants with accessthreat: network exposed
RISK SCORE
0/ 100 risk
low findings+5
high findings+50
medium findings+60
capped at100
VULNERABILITY ANALYSIS · 7 findings in 7 blocks2 HIGH · 4 MEDIUM
HIGH1 finding
src/tools.py:1
1Tools exposed: delete_recipe, delete_shopping_list, delete_shopping_list_item, delete_category, delete_tag, delete_mealplansrc/server.py:116→src/tools.py:?
// Network-exposed MCP server; exploitable via crafted prompts to the LLM.
EXPLAINThe MCP server exposes multiple destructive delete operations (delete_recipe, delete_shopping_list, delete_shopping_list_item, delete_category, delete_tag, delete_mealplan) that allow permanent deletion of data. While the intended purpose is recipe management, these tools provide capability to destroy data without any confirmation or rollback mechanism.
IMPACTA compromised LLM or malicious prompt could delete recipes, shopping lists, categories, tags, or meal plans, causing permanent data loss.
FIXImplement confirmation steps before deletion, add soft-delete functionality, or restrict delete operations to specific authorized users.
HIGH1 finding
src/tools.py:1
1Tools exposed: add_recipes_to_shopping_list_bulk, create_shopping_list_items_bulk, update_shopping_list_items_bulk, delete_shopping_list_items_bulk, create_mealplan_bulksrc/server.py:116→src/tools.py:?
// Network-exposed MCP server; exploitable via crafted prompts to the LLM.
EXPLAINThe server exposes bulk operations that can add, update, or delete many items at once. These tools can be abused to rapidly modify large amounts of data, potentially overwhelming the system or causing unintended changes.
IMPACTAn attacker could add hundreds of items to a shopping list, delete all items in bulk, or create many meal plan entries, leading to data corruption or denial of service.
FIXAdd rate limiting, maximum batch sizes, and confirmation prompts for bulk operations.
MEDIUM1 finding
src/mealie/recipe.py:1
1def create_recipe(self, recipe_data: Dict[str, Any]) -> Dict[str, Any]:
2 ...
3 return self._handle_request("POST", "/api/recipes", json=recipe_data)
4
5def update_recipe(self, recipe_id: str, recipe_data: Dict[str, Any]) -> Dict[str, Any]:
6 ...
7 return self._handle_request("PUT", f"/api/recipes/{recipe_id}", json=recipe_data)src/server.py:116→src/tools.py:?→src/mealie/recipe.py:?
// Network-exposed MCP server; exploitable via crafted prompts to the LLM.
EXPLAINThe create_recipe and update_recipe tools accept arbitrary dictionaries without validating the structure or content. This could allow injection of malicious data into the Mealie database, such as excessively large fields, script content, or unexpected fields.
IMPACTAn attacker could inject malformed data, potentially causing application errors, XSS in web views, or database corruption.
FIXImplement input validation using a schema (e.g., Pydantic models) to ensure only expected fields with correct types are accepted.
MEDIUM1 finding
src/mealie/categories.py:63
63def create_category(self, name: str) -> Dict[str, Any]:
64 if not name:
65 raise ValueError("Category name cannot be empty")
66 payload = {"name": name}
67 logger.info({"message": "Creating category", "name": name})
68 return self._handle_request("POST", "/api/organizers/categories", json=payload)src/server.py:116→src/tools.py:?→src/mealie/categories.py:63
// Network-exposed MCP server; exploitable via crafted prompts to the LLM.
EXPLAINThe create_category, create_tag, and create_food tools only check for empty strings but do not validate length, character set, or content. This could allow creation of categories/tags/foods with extremely long names or special characters that might cause issues.
IMPACTAn attacker could create categories with names that cause display issues, SQL injection (if backend is vulnerable), or denial of service via excessive length.
FIXAdd validation for maximum length and allowed characters on name fields.
MEDIUM1 finding
src/mealie/shopping_list.py:1
1def add_shopping_list_item(self, list_id: str, item_data: Dict[str, Any]) -> Dict[str, Any]:
2 ...
3 return self._handle_request("POST", f"/api/households/shopping-lists/{list_id}/items", json=item_data)
4
5def update_shopping_list_item(self, item_id: str, item_data: Dict[str, Any]) -> Dict[str, Any]:
6 ...
7 return self._handle_request("PUT", f"/api/households/shopping-lists/items/{item_id}", json=item_data)src/server.py:116→src/tools.py:?→src/mealie/shopping_list.py:?
// Network-exposed MCP server; exploitable via crafted prompts to the LLM.
EXPLAINShopping list item creation and update tools accept arbitrary dictionaries without validation. This could allow setting unexpected fields or values that might corrupt the shopping list.
IMPACTAn attacker could add items with malformed data, potentially causing application errors or data corruption.
FIXImplement input validation using a schema to ensure only expected fields with correct types are accepted.
MEDIUM1 finding
src/mealie/mealplan.py:1
1def create_mealplan(self, mealplan_data: Dict[str, Any]) -> Dict[str, Any]:
2 ...
3 return self._handle_request("POST", "/api/households/mealplans", json=mealplan_data)
4
5def update_mealplan(self, mealplan_id: str, mealplan_data: Dict[str, Any]) -> Dict[str, Any]:
6 ...
7 return self._handle_request("PUT", f"/api/households/mealplans/{mealplan_id}", json=mealplan_data)src/server.py:116→src/tools.py:?→src/mealie/mealplan.py:?
// Network-exposed MCP server; exploitable via crafted prompts to the LLM.
EXPLAINMeal plan creation and update tools accept arbitrary dictionaries without validation. This could allow setting invalid dates, recipe IDs, or other fields that might corrupt the meal plan.
IMPACTAn attacker could create meal plans with invalid data, potentially causing application errors or data corruption.
FIXImplement input validation using a schema to ensure only expected fields with correct types are accepted.
LOW1 finding
src/server.py:98
98MEALIE_BASE_URL = os.getenv("MEALIE_BASE_URL")
99MEALIE_API_KEY = os.getenv("MEALIE_API_KEY")
100if not MEALIE_BASE_URL or not MEALIE_API_KEY:
101 raise ValueError(
102 "MEALIE_BASE_URL and MEALIE_API_KEY must be set in environment variables."
103 )src/server.py:98-103
// Network-exposed MCP server; requires access to server environment or logs.
EXPLAINThe Mealie API key is loaded from an environment variable and used for authentication. While this is standard practice, the key could be exposed through debug logging or error messages. The client initialization logs the base URL but not the key directly, but error responses might leak it.
IMPACTIf an attacker gains access to the environment or logs, they could obtain the API key and directly access the Mealie API.
FIXEnsure API keys are never logged. Consider using a secrets manager or encrypted storage. Review logging configuration to redact sensitive data.
◷ 5/31/2026
Findings are produced by automated LLM analysis and may include false positives or miss issues. Verify independently before acting.