Skip to main content
Vulnerability Database/CVE-2026-93736

CVE-2026-93736: Mealie Information Disclosure Vulnerability

CVE-2026-93736 is an information disclosure flaw in Mealie that allows authenticated attackers to access other users' recipe ratings and favorites. This post explains its impact, affected versions, and mitigation steps.

Updated:

CVE-2026-93736 Overview

CVE-2026-93736 is an Insecure Direct Object Reference (IDOR) vulnerability in Mealie, an open-source self-hosted recipe manager. Versions before 3.21.0 fail to validate user ownership in the ratings and favorites API endpoints. Any authenticated user can read another user's recipe ratings and favorites by substituting an arbitrary user identifier in the URL path. The exposed data includes private recipe identifiers, numeric rating values, and favorite flags belonging to users in different groups or households. The flaw is tracked under CWE-639: Authorization Bypass Through User-Controlled Key.

Critical Impact

Authenticated attackers can enumerate private recipe metadata and user preferences across tenant boundaries, breaking the multi-household isolation model of Mealie.

Affected Products

  • Mealie versions prior to 3.21.0
  • Mealie v3.20.1 (confirmed vulnerable via referenced source)
  • Self-hosted Mealie deployments exposing the /users/{id}/ratings and /users/{id}/favorites endpoints

Discovery Timeline

  • 2026-09-18 - CVE-2026-93736 published to the National Vulnerability Database (NVD)
  • 2026-09-22 - Last updated in the NVD database

Technical Details for CVE-2026-93736

Vulnerability Analysis

Mealie exposes two authenticated endpoints for reading a user's recipe ratings and favorites: GET /users/{id}/ratings and GET /users/{id}/favorites. In versions before 3.21.0, both handlers accept a UUID from the URL path and pass it directly to the repository query without verifying that the caller owns the referenced account. Any authenticated user can supply another user's UUID and receive their ratings collection.

The returned payload includes recipe identifiers, rating values, and favorite flags. Because Mealie supports multiple groups and households on a single instance, this crosses tenant boundaries and reveals private recipe references belonging to unrelated users. The impact is limited to confidentiality of ratings and favorites data — write operations and other resources are not affected by this specific flaw.

Root Cause

The root cause is a missing authorization check in mealie/routes/users/ratings.py. The get_ratings and get_favorites route handlers rely solely on authentication middleware and do not compare the path parameter id against the authenticated principal. The upstream repository method user_ratings.get_by_user(id) trusts the caller-supplied UUID as the lookup key.

Attack Vector

Exploitation requires only a valid, low-privilege account on the target Mealie instance. An attacker authenticates, obtains a session token, then issues GET requests against /api/users/{victim_uuid}/ratings or /api/users/{victim_uuid}/favorites. Victim UUIDs may be harvested from other enumeration endpoints or guessed if predictable. No user interaction is required from the victim.

python
# Security patch for mealie/routes/users/ratings.py (commit 6889101a)
    @router.get("/{id}/ratings", response_model=UserRatings[UserRatingOut])
    async def get_ratings(self, id: UUID4):
        """Get user's rated recipes"""
+       assert_user_change_allowed(id, self.user, self.user)
        return UserRatings(ratings=self.repos.user_ratings.get_by_user(id))

    @router.get("/{id}/favorites", response_model=UserRatings[UserRatingOut])
    async def get_favorites(self, id: UUID4):
        """Get user's favorited recipes"""
+       assert_user_change_allowed(id, self.user, self.user)
        return UserRatings(ratings=self.repos.user_ratings.get_by_user(id, favorites_only=True))

    @router.post("/{id}/ratings/{slug}")

Source: GitHub Commit 6889101a. The fix adds assert_user_change_allowed(id, self.user, self.user) to both handlers, forcing the requested user ID to match the authenticated principal before the repository lookup executes.

Detection Methods for CVE-2026-93736

Indicators of Compromise

  • Successful HTTP 200 responses on /api/users/{id}/ratings or /api/users/{id}/favorites where {id} does not match the authenticated user's UUID
  • A single session issuing sequential requests to /api/users/{id}/ratings with varying UUID path parameters, consistent with enumeration
  • Application logs showing repeated get_ratings or get_favorites calls from one account referencing multiple distinct user UUIDs

Detection Strategies

  • Parse reverse-proxy or FastAPI access logs and correlate the authenticated user with the {id} path segment. Alert when they diverge.
  • Baseline normal ratings and favorites read patterns per account. Flag accounts that request more distinct target UUIDs per hour than the baseline permits.
  • Deploy a Web Application Firewall (WAF) rule that inspects the JWT subject claim and compares it against the URL path for these endpoints.

Monitoring Recommendations

  • Enable verbose application logging for the /users/{id}/ratings and /users/{id}/favorites routes and forward logs to a centralized SIEM.
  • Monitor for unusually high request volumes to the users API namespace from any single session token.
  • Review authentication logs for newly registered accounts followed by rapid enumeration of user endpoints, which is consistent with opportunistic abuse.

How to Mitigate CVE-2026-93736

Immediate Actions Required

  • Upgrade all Mealie deployments to version 3.21.0 or later, which is the fixed release published on the Mealie v3.21.0 release page.
  • Audit access logs since deployment for cross-user requests to /api/users/{id}/ratings and /api/users/{id}/favorites.
  • Restrict Mealie instance registration if the deployment is internet-facing, to limit the pool of authenticated attackers.

Patch Information

The fix is delivered in commit 6889101a, merged via Pull Request #7903 addressing Issue #7909. The patch adds an assert_user_change_allowed authorization check to both endpoints, ensuring the path UUID matches the authenticated user. Full advisory details are available in the VulnCheck Advisory for Mealie.

Workarounds

  • Place Mealie behind a reverse proxy that rewrites or validates the {id} segment of /api/users/{id}/ratings and /api/users/{id}/favorites against the session's user claim.
  • Temporarily block external access to /api/users/*/ratings and /api/users/*/favorites at the proxy layer until the upgrade is applied.
  • Disable self-service account registration to prevent unauthenticated adversaries from obtaining the low-privilege access required to exploit the flaw.
bash
# Example NGINX rule to block the vulnerable endpoints until patched
location ~* ^/api/users/[^/]+/(ratings|favorites)$ {
    return 403;
}

# Verify the running Mealie version is 3.21.0 or later
docker exec mealie cat /app/mealie/__init__.py | grep -i version

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.