CVE-2026-33405 Overview
CVE-2026-33405 is a stored HTML injection vulnerability affecting the Pi-hole Admin Interface, a web interface for managing Pi-hole, a popular network-level ad and internet tracker blocking application. The vulnerability exists in versions 6.0 through 6.4 of the web interface, where the formatInfo() function in queries.js fails to properly escape user-controlled data when rendering expanded query rows in the Query Log.
Critical Impact
Attackers with administrative access can inject malicious HTML content into the Query Log that persists and renders for other administrators, potentially leading to UI manipulation, phishing attacks, or information disclosure. While JavaScript execution is blocked by the server's Content Security Policy (CSP), the HTML injection itself can still be leveraged for social engineering attacks.
Affected Products
- Pi-hole Web Interface versions 6.0 to 6.4
- Pi-hole installations using the vulnerable admin dashboard
- Self-hosted Pi-hole deployments with exposed admin interfaces
Discovery Timeline
- 2026-04-06 - CVE CVE-2026-33405 published to NVD
- 2026-04-09 - Last updated in NVD database
Technical Details for CVE-2026-33405
Vulnerability Analysis
This vulnerability is classified as CWE-79 (Cross-Site Scripting), specifically manifesting as a stored HTML injection flaw. The root issue lies in inconsistent output encoding within the Pi-hole web interface's JavaScript code.
The formatInfo() function in queries.js is responsible for rendering detailed information when a user expands a query row in the Query Log interface. This function directly renders three specific fields into HTML without proper escaping: data.upstream, data.client.ip, and data.ede.text. An attacker who can control these fields can inject arbitrary HTML content that will be stored and later rendered for any administrator viewing the Query Log.
Notably, the same fields are properly escaped in the table view's rowCallback function, confirming that this vulnerability was an oversight rather than a deliberate design decision. The inconsistency between the two rendering paths indicates a code review gap.
Root Cause
The vulnerability stems from missing output encoding in the formatInfo() function within queries.js. While the main table view correctly sanitizes the data.upstream, data.client.ip, and data.ede.text fields using proper HTML escaping, the expanded row detail view bypasses this protection by directly inserting the raw field values into the DOM. This inconsistent application of security controls creates an injection point that attackers can exploit.
Attack Vector
The attack requires an adversary with high-level privileges (administrative access) to inject malicious HTML content through DNS query data that gets logged and displayed in the Query Log. When another administrator expands a query row containing the malicious payload, the injected HTML renders in their browser context.
The exploitation scenario involves:
- An attacker with admin access crafting DNS queries or manipulating logged data to include malicious HTML in the upstream, client.ip, or ede.text fields
- The malicious content being stored in the Pi-hole query log database
- A victim administrator viewing the Query Log and expanding the affected row
- The formatInfo() function rendering the unescaped HTML in the victim's browser
While the server's CSP (script-src 'self') prevents JavaScript execution, attackers can still leverage HTML injection for UI spoofing, form injection for credential harvesting, or embedding malicious iframes.
Detection Methods for CVE-2026-33405
Indicators of Compromise
- Unusual HTML tags or entities appearing in Query Log fields such as upstream, client.ip, or ede.text
- Query log entries containing embedded iframe, form, or anchor tags with suspicious destinations
- Reports from administrators of unexpected UI elements or overlays in the Query Log interface
- Anomalous DNS query patterns that include HTML markup in hostnames or responses
Detection Strategies
- Review Pi-hole query logs for entries containing HTML special characters (<, >, ", ') in unexpected fields
- Implement log analysis to flag query entries with potential HTML injection patterns
- Monitor administrative session activity for unusual Query Log access patterns
- Deploy browser-based security tools that can detect DOM manipulation attempts
Monitoring Recommendations
- Enable verbose logging on the Pi-hole admin interface to capture access patterns
- Configure alerts for query log entries matching common HTML injection patterns (e.g., <script, <iframe, <form, onclick)
- Regularly audit administrative access to the Pi-hole interface
- Monitor for CSP violation reports which may indicate attempted script injection
How to Mitigate CVE-2026-33405
Immediate Actions Required
- Upgrade Pi-hole Web Interface to version 6.5 or later immediately
- Audit query logs for any existing malicious HTML content and purge affected entries
- Restrict administrative access to the Pi-hole interface to trusted networks only
- Review and limit the number of accounts with administrative privileges
Patch Information
The vulnerability is fixed in Pi-hole Web Interface version 6.5. The patch addresses the missing output encoding in the formatInfo() function by applying proper HTML escaping to the data.upstream, data.client.ip, and data.ede.text fields, bringing them in line with the security measures already implemented in the rowCallback function.
Users should update their Pi-hole installation using the standard update mechanism. For detailed information about the fix, see the GitHub Security Advisory.
Workarounds
- Implement network-level access controls to limit who can reach the Pi-hole admin interface
- Deploy a reverse proxy with additional input filtering and output encoding
- Disable the expanded query detail view if not operationally required
- Consider placing the Pi-hole admin interface behind a VPN or requiring additional authentication
# Configuration example - Restrict admin interface access via firewall
# Allow only specific trusted IP addresses to access Pi-hole admin
sudo iptables -A INPUT -p tcp --dport 80 -s 192.168.1.100 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -s 192.168.1.101 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j DROP
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

