Back to skill

Security audit

Mealie Recipe Manager

Security checks for vulnerabilities and agentic risk

Overview

This Mealie skill is coherent, but it needs review because it can delete Mealie data and may send its API token over unencrypted HTTP.

Review before installing. Use only an HTTPS Mealie URL, create a dedicated least-privilege Mealie API token, store the .env file with restrictive permissions, and be careful with delete commands because the script executes them immediately without confirmation.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mealie.js:74
Finding

Bearer API Token Can Be Transmitted over Unencrypted HTTP

Content
View full analysis
{ const path = endpoint.startsWith('/api') ? endpoint : `/api${endpoint}`; const options = { hostname: urlObj.hostname, port: urlObj.port || (isHttps ? 443 : 80), path: path, method: method, headers: { 'Authorization': `Bearer ${API_TOKEN}`, 'Content-Type': 'application/json' } }; ``` ### Technical Analysis The client selects the plaintext Node.js HTTP module whenever `MEALIE_URL` does not use the `https:` protocol. It nevertheless includes `MEALIE_API_TOKEN` as a bearer credential in every API request. Bearer tokens provide access based solely on possession. When sent over HTTP, neither the authorization header nor the request and response bodies receive transport encryption or server authentication. An attacker able to observe or manipulate traffic between the client and the Mealie server can therefore capture the token, inspect private Mealie data, modify traffic, or impersonate the server. The access to `~/.openclaw/.env` and the skill-level `.env` is consistent with the declared authentication functionality and parsing is limited to `MEALIE_URL` and `MEALIE_API_TOKEN`. The security issue is not the documented credential-file access itself, but the possibility of transmitting the loaded secret over an insecure transport. ### Attack Path 1. The user or deployment configures `MEALIE_URL` with an `http://` endpoint. 2. The Skill reads `MEALIE_API_TOKEN` from the process environment, the skill-level `.env`, or ...[truncated 1401 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mealie.js (reported line 36)May include surrounding context.

js
return;
  }
  
  // Try skill-level .env first
  const skillEnvPath = path.join(__dirname, '..', '.env');
  if (fs.existsSync(skillEnvPath)) {
    const content = fs.readFileSync(skillEnvPath, 'utf8');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mealie.js (reported line 48)May include surrounding context.

js
return;
  }
  
  // Try skill-level .env first
  const skillEnvPath = path.join(__dirname, '..', '.env');
  if (fs.existsSync(skillEnvPath)) {
    const content = fs.readFileSync(skillEnvPath, 'utf8');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mealie.js (reported line 68)May include surrounding context.

js
return;
  }
  
  // Try skill-level .env first
  const skillEnvPath = path.join(__dirname, '..', '.env');
  if (fs.existsSync(skillEnvPath)) {
    const content = fs.readFileSync(skillEnvPath, 'utf8');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mealie.js (reported line 37)May include surrounding context.

js
}
  
  // Try skill-level .env first
  const skillEnvPath = path.join(__dirname, '..', '.env');
  if (fs.existsSync(skillEnvPath)) {
    const content = fs.readFileSync(skillEnvPath, 'utf8');
    content.split('\n').forEach(line => {

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mealie.js (reported line 49)May include surrounding context.

js
}
  
  // Try skill-level .env first
  const skillEnvPath = path.join(__dirname, '..', '.env');
  if (fs.existsSync(skillEnvPath)) {
    const content = fs.readFileSync(skillEnvPath, 'utf8');
    content.split('\n').forEach(line => {

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mealie.js (reported line 68)May include surrounding context.

js
}
  
  // Try skill-level .env first
  const skillEnvPath = path.join(__dirname, '..', '.env');
  if (fs.existsSync(skillEnvPath)) {
    const content = fs.readFileSync(skillEnvPath, 'utf8');
    content.split('\n').forEach(line => {

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
77% confidence
Finding

The skill instructs users to store a long-lived API token in global or skill-level .env files under the user’s home directory, creating persistent local credential storage. If the host is shared, backups are exposed, filesystem permissions are weak, or another tool/process can read those files, the token could be stolen and used to access or modify the Mealie instance.

Content

Scanner excerpt · SKILL.md (reported line 18)May include surrounding context.

md
## Environment Variables

Set these in your agent's `.env` (`~/.openclaw/.env`) or create a skill-level `.env` at `~/.openclaw/skills/mealie/.env`:

- `MEALIE_URL` — Your Mealie instance URL (e.g., `https://recipes.example.com`)
- `MEALIE_API_TOKEN` — Your API token (create at `/user/profile/api-tokens` in Mealie)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises destructive and state-changing operations such as deleting recipes, deleting items, and modifying meal plans without any warning, confirmation guidance, or caution about irreversible changes. In an agent setting, this increases the risk of accidental data loss or unintended modification of a user’s Mealie instance, especially because the skill uses an authenticated API token with write access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The delete-recipe command performs an irreversible destructive action immediately from CLI input without any confirmation prompt, dry-run mode, or safety flag. In an agent context, accidental invocation, prompt confusion, or misuse could delete user data with little friction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The delete-item command removes shopping-list items immediately based only on supplied identifiers and provides no confirmation or warning. In an automation or agent-driven workflow, this increases the chance of unintended data loss from mistakes or manipulated inputs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes this skill as interacting with Mealie for recipes, shopping lists, and meal plans. The code also exposes commands for household statistics, tags, and categories, which are additional Mealie capabilities not reflected in that stated scope. These are not necessary implementation details for the described functions and broaden the skill’s behavior beyond what the manifest claims.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code explicitly formats dates using toLocaleDateString('en-US'), which imposes a specific locale regardless of the user's preferences or environment. This is a natural-language/locale policy issue because the skill does not offer a locale choice or document why US English formatting is required.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.