Skip to content



v1.0.0beta-3 and Under - Recipe Scraper: Server Side Request Forgery Lead To Denial Of Service

CWE-918: Server-Side Request Forgery (SSRF)

In this case if a attacker try to load a huge file then server will try to load the file and eventually server use its all memory which will dos the server


HTML is now scraped via a Stream and canceled after a 15 second timeout to prevent arbitrary data from being loaded into the server.

v1.0.0beta-3 and Under - Recipe Assets: Remote Code Execution

CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine

As a low privileged user, Create a new recipe and click on the "+" to add a New Asset. Select a file, then proxy the request that will create the asset.

Since mealie/routes/recipe/ is calling slugify on the name POST parameter, we use $ which slugify() will remove completely.

Since mealie/routes/recipe/ is concatenating raw user input from the extension POST parameter into the variable file_name, which ultimately gets used when writing to disk, we can use a directory traversal attack in the extension (e.g. ./../../../tmp/pwn.txt) to write the file to arbitrary location on the server.

As an attacker, now that we have a strong attack primitive, we can start getting creative to get RCE. Since the files were being created by root, we could add an entry to /etc/passwd, create a crontab, etc. but since there was templating functionality in the application that peaked my interest. The PoC in the HTTP request above creates a Jinja2 template at /app/data/template/pwn.html. Since Jinja2 templates execute Python code when rendered, all we have to do now to get code execution is render the malicious template. This was easy enough.


We've added proper path sanitization to ensure that the user is not allowed to write to arbitrary locations on the server.

Breaking Change Incoming

As this has shown a significant area of exposure in the templates that Mealie was provided for exporting recipes, we'll be removing this feature in the next Beta release and will instead rely on the community to provide tooling around transforming recipes using templates. This will significantly limit the possible exposure of users injecting malicious templates into the application. The template functionality will be completely removed in the next beta release v1.0.0beta-5

All version Markdown Editor: Cross Site Scripting

CWE-79: Cross-site Scripting (XSS) - Stored

A low privilege user can insert malicious JavaScript code into the Recipe Instructions which will execute in another person's browser that visits the recipe.

<img src=x onerror=alert(document.domain)>


This issues is present on all pages that allow markdown input. This error has been mitigated by wrapping the 3rd Party Markdown component and using the domPurify library to strip out the dangerous HTML.

v1.0.0beta-3 and Under - Image Scraper: Server-Side Request Forgery

CWE-918: Server-Side Request Forgery (SSRF)

In the recipe edit page, is possible to upload an image directly or via an URL provided by the user. The function that handles the fetching and saving of the image via the URL doesn't have any URL verification, which allows to fetch internal services.

Furthermore, after the resource is fetch, there is no MIME type validation, which would ensure that the resource is indeed an image. After this, because there is no extension in the provided URL, the application will fallback to jpg, and original for the image name.

Then the result is saved to disk with the original.jpg name, that can be retrieved from the following URL: http:///api/media/recipes//images/original.jpg. This file will contain the full response of the provided URL.


An attacker can get sensitive information of any internal-only services running. For example, if the application is hosted on Amazon Web Services (AWS) platform, its possible to fetch the AWS API endpoint,, which returns API keys and other sensitive metadata.


Two actions were taken to reduce exposure to SSRF in this case.

  1. The application will not prevent requests being made to local resources by checking for localhost or domain names.
  2. The mime-type of the response is now checked prior to writing to disk.

If either of the above actions prevent the user from uploading images, the application will alert the user of what error occurred.

Bug Fixes

  • For erroneously-translated datetime config (#1362)
  • Fixed text color on RecipeCard in RecipePrintView and implemented ingredient sections (#1351)
  • Ingredient sections lost after parsing (#1368)
  • Increased float rounding precision for CRF parser (#1369)
  • Infinite scroll bug on all recipes page (#1393)
  • Fast fail of bulk importer (#1394)
  • Bump @mdi/js from 5.9.55 to 6.7.96 in /frontend (#1279)
  • Bump @nuxtjs/i18n from 7.0.3 to 7.2.2 in /frontend (#1288)
  • Bump date-fns from 2.23.0 to 2.28.0 in /frontend (#1293)
  • Bump fuse.js from 6.5.3 to 6.6.2 in /frontend (#1325)
  • Bump core-js from 3.17.2 to 3.23.1 in /frontend (#1383)
  • All-recipes page now sorts alphabetically (#1405)
  • Sort recent recipes by created_at instead of date_added (#1417)
  • Only show scaler when ingredients amounts enabled (#1426)
  • Add missing types for API token deletion (#1428)
  • Entry nutrition checker (#1448)
  • Use == operator instead of is_ for sql queries (#1453)
  • Use mtime instead of ctime for backup dates (#1461)
  • Mealplan pagination (#1464)
  • Properly use pagination for group event notifies (#1512)


  • Add go bulk import example (#1388)
  • Fix old link
  • Pagination and filtering, and fixed a few broken links (#1488)


  • Toggle display of ingredient references in recipe instructions (#1268)
  • Add custom scaling option (#1345)
  • Implemented "order by" API parameters for recipe, food, and unit queries (#1356)
  • Implement user favorites page (#1376)
  • Extend Apprise JSON notification functionality with programmatic data (#1355)
  • Mealplan-webhooks (#1403)
  • Added "last-modified" header to supported record types (#1379)
  • Re-write get all routes to use pagination (#1424)
  • Advanced filtering API (#1468)
  • Restore frontend sorting for all recipes (#1497)
  • Implemented local storage for sorting and dynamic sort icons on the new recipe sort card (1506)
  • create new foods and units from their Data Management pages (#1511)

Miscellaneous Tasks

  • Bump dev deps (#1418)
  • Bump @vue/runtime-dom in /frontend (#1423)
  • Backend page_all route cleanup (#1483)


  • Remove depreciated repo call (#1370)


  • Tame typescript beast


  • Improve parser ui text display (#1437)