From ce88ed6841ae1d66440a4b70c0b14536241a443c Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Sun, 19 Jul 2026 21:41:30 -0500 Subject: [PATCH] fix: harden server-initiated HTTP against SSRF and DNS rebinding Route all server-initiated outbound HTTP through one SSRF-protected layer: - Resolve each host once, validate every resolved address (private, loopback, link-local, CGNAT 100.64/10, multicast, reserved, unspecified, IPv4-mapped IPv6), and reject if any is unsafe. - Pin the connection to the validated address via curl's RESOLVE option so curl cannot re-resolve to a rebound IP (closes the validate-then-connect TOCTOU). Uses getaddrinfo so IPv6 records are checked too. - Add a sync SafeTransport and safehttp.post, and move the webhook and recipe-action paths off raw requests.post so they are guarded like the scraper. - Add HTTP_ALLOW_LIST / HTTP_DISALLOW_LIST settings (deny > allow > default) so operators can reach an internal server or block extra hosts. Apprise notifications egress through the third-party library and are not covered here. --- .../installation/backend-config.md | 2 + mealie/core/settings/settings.py | 17 ++ mealie/pkgs/safehttp/__init__.py | 12 +- mealie/pkgs/safehttp/transport.py | 198 ++++++++++++++---- .../controller_group_recipe_actions.py | 8 +- .../services/event_bus_service/publisher.py | 12 +- mealie/services/recipe/recipe_data_service.py | 38 +++- mealie/services/scraper/scraper_strategies.py | 4 + .../test_group_recipe_actions.py | 6 +- .../test_group_webhooks.py | 6 +- tests/unit_tests/pkgs/test_safehttp.py | 189 +++++++++++++++++ 11 files changed, 435 insertions(+), 57 deletions(-) create mode 100644 tests/unit_tests/pkgs/test_safehttp.py diff --git a/docs/docs/documentation/getting-started/installation/backend-config.md b/docs/docs/documentation/getting-started/installation/backend-config.md index 6b030c0fc..e16f73225 100644 --- a/docs/docs/documentation/getting-started/installation/backend-config.md +++ b/docs/docs/documentation/getting-started/installation/backend-config.md @@ -30,6 +30,8 @@ | SECURITY_MAX_LOGIN_ATTEMPTS | 5 | Maximum times a user can provide an invalid password before their account is locked | | SECURITY_USER_LOCKOUT_TIME | 24 | Time in hours for how long a users account is locked | | ALLOWED_IFRAME_HOSTS | `""` | Comma-separated extra hostnames allowed as `