CVE-2026-33149 Overview
CVE-2026-33149 is a Host Header Injection vulnerability in Tandoor Recipes, an open-source application for managing recipes, planning meals, and building shopping lists. Versions up to and including 2.5.3 set ALLOWED_HOSTS = '*' by default, which causes Django to accept any value in the HTTP Host header without validation. This misconfiguration allows attackers to manipulate server-generated absolute URLs, leading to critical security impacts including invite link poisoning.
Critical Impact
Attackers can poison invite links sent via email, redirecting victims to attacker-controlled servers and stealing authentication tokens that grant unauthorized access to the application.
Affected Products
- Tandoor Recipes versions up to and including 2.5.3
Discovery Timeline
- 2026-03-26 - CVE-2026-33149 published to NVD
- 2026-03-26 - Last updated in NVD database
Technical Details for CVE-2026-33149
Vulnerability Analysis
The vulnerability stems from an insecure default configuration in Tandoor Recipes. The application uses Django's request.build_absolute_uri() method to generate absolute URLs in multiple contexts, including invite link emails, API pagination responses, and OpenAPI schema generation. When combined with the permissive ALLOWED_HOSTS = '*' setting, this creates a Host Header Injection vulnerability (CWE-644: Improper Neutralization of HTTP Headers for Scripting Syntax).
In a typical exploitation scenario, an attacker sends a request to the application with a maliciously crafted Host header pointing to an attacker-controlled domain. When an administrator creates an invite for a new user, the application generates an invite email containing an absolute URL. Because the Host header is not validated, the generated URL points to the attacker's server instead of the legitimate application server.
When the victim clicks the poisoned invite link, the invite token is sent to the attacker's server. The attacker can then replay this token at the real application to complete the registration process, potentially gaining unauthorized access to the system.
Root Cause
The root cause is the default configuration setting ALLOWED_HOSTS = '*' in Django, which disables Host header validation entirely. This allows the application to accept and trust any Host header value provided in incoming HTTP requests. Combined with the use of request.build_absolute_uri() for generating URLs in security-sensitive contexts like invite emails, this creates a reliable attack vector for token theft.
Attack Vector
The attack is network-based and requires the attacker to be able to send HTTP requests to the vulnerable Tandoor Recipes instance. The attack flow involves:
- Attacker identifies a Tandoor Recipes instance with the default ALLOWED_HOSTS configuration
- Attacker monitors for invite creation activity or socially engineers an administrator to create an invite
- When the invite request is processed, the attacker injects a malicious Host header pointing to their controlled domain
- The application generates an invite email with a poisoned URL containing the attacker's domain
- The victim receives the email and clicks the invite link
- The invite token is sent to the attacker's server
- Attacker uses the captured token to register on the legitimate application
The vulnerability requires user interaction (the victim must click the poisoned link) and elevated privileges (typically admin-level access to create invites), but the impact crosses security boundaries as it compromises confidentiality and integrity of user accounts.
Detection Methods for CVE-2026-33149
Indicators of Compromise
- Unusual Host header values in web server access logs that don't match the expected application domain
- Failed authentication attempts or account registrations from unexpected IP addresses using valid invite tokens
- User reports of receiving invite emails with URLs pointing to unfamiliar domains
Detection Strategies
- Implement web application firewall (WAF) rules to detect and block requests with Host headers that don't match the legitimate application domain
- Monitor Django application logs for requests where the Host header differs from configured domain names
- Review outbound email logs for invite links containing unexpected domains
- Enable alerting for invite token usage from IP addresses that don't match the original invite request
Monitoring Recommendations
- Configure logging to capture full HTTP headers for all requests to the application
- Implement anomaly detection for Host header values in request logs
- Monitor email gateway logs for emails containing suspicious URLs in invite links
- Set up alerts for invite token redemption patterns that indicate token theft scenarios
How to Mitigate CVE-2026-33149
Immediate Actions Required
- Configure ALLOWED_HOSTS in your Tandoor Recipes Django settings to include only your legitimate domain names
- Review recent invite emails and verify URLs point to the correct application domain
- Audit user accounts created via invites for any suspicious registrations
- Invalidate any pending invite tokens and regenerate them after fixing the configuration
Patch Information
As of the publication date, it is unknown if a patched version is available. Organizations should monitor the GitHub Security Advisory for updates regarding an official fix. In the meantime, the configuration workaround described below should be applied immediately.
Workarounds
- Set ALLOWED_HOSTS to a list containing only your valid domain names (e.g., ALLOWED_HOSTS = ['recipes.example.com', 'www.recipes.example.com'])
- Deploy a reverse proxy or load balancer that validates and normalizes Host headers before forwarding requests to the application
- Implement additional email security controls to verify outbound links match expected domains
- Consider adding a web application firewall rule to reject requests with unexpected Host header values
# Configuration example for Django settings
# Edit your Tandoor Recipes configuration to restrict ALLOWED_HOSTS
# Replace the wildcard with your specific domain(s)
# In .env or environment configuration:
ALLOWED_HOSTS=recipes.yourdomain.com,www.recipes.yourdomain.com
# Or in Django settings.py:
# ALLOWED_HOSTS = ['recipes.yourdomain.com', 'www.recipes.yourdomain.com']
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

