Aug 24, 2026·6 min read·2 visits
Unvalidated ALPN parsing in netfoil permits terminal log injection and memory exhaustion.
netfoil, an allowlist-based DNS proxy, failed to sanitize ALPN fields parsed from untrusted DNS-over-HTTPS (DoH) HTTPS Resource Records. This allowed attackers to inject ANSI escape sequences into log files or trigger Denial of Service (DoS) via uncontrolled memory allocations.
netfoil is a client-side, minimal DNS proxy built in Go that relies on DNS-over-HTTPS (DoH) to secure upstream queries and apply allowlists.
During standard resolution operations, the proxy parses incoming DNS resource records, including HTTPS Resource Records (RR) defined by RFC 9460. These records contain Application-Layer Protocol Negotiation (ALPN) parameters used to negotiate client-server protocol capabilities.
Prior to version v0.5.0, netfoil did not validate or sanitize the parsed ALPN parameters. Any raw byte sequence returned in the ALPN field by an upstream server was converted directly into Go strings and subsequently logged or stored.
This lack of validation exposed the proxy to log poisoning via ANSI escape sequence injection and denial of service via memory exhaustion. In addition, the system lacked structured logging for single-byte DNS response codes (RCODE), logging raw numbers directly to standard output.
The vulnerability is situated within the parsing function readALPN in internal/dns/dns_https.go. This function processes raw byte slices containing ALPN identifiers.
RFC 9460 defines the ALPN parameter in HTTPS records as a list of length-prefixed protocol identifiers. The unpatched readALPN implementation sequentially read each identifier via a helper function readPart and converted the raw bytes directly to a Go string.
No checks were performed to verify if the converted strings matched legitimate ALPN values, nor were there limitations on the number of unique or repetitive strings parsed.
An attacker capable of manipulating the upstream DNS response could inject non-printable characters, terminal escape sequences, or millions of duplicate keys. The proxy would attempt to process and store all incoming values, causing excessive memory allocations and terminal-side command execution through output manipulation.
Below is the comparison of the vulnerable implementation versus the patched implementation in internal/dns/dns_https.go.
// VULNERABLE: internal/dns/dns_https.go
func readALPN(data []byte) ([]string, error) {
p := bytes.NewBuffer(data)
parts := make([]string, 0)
for {
if p.Len() == 0 {
break
}
part, err := readPart(p)
if err != nil {
return nil, err
}
parts = append(parts, string(part)) // Direct unvalidated conversion
}
return parts, nil
}The patch introduced strict allowlist matching and a uniqueness check using a map-based set to control memory footprint.
// PATCHED: internal/dns/dns_https.go
func readALPN(data []byte) ([]string, error) {
p := bytes.NewBuffer(data)
alpnSet := make(map[string]struct{})
result := make([]string, 0)
for {
if p.Len() == 0 {
break
}
part, err := readPart(p)
if err != nil {
return nil, err
}
alpn := string(part)
switch alpn {
case "h2":
_, found := alpnSet[alpn]
if !found {
result = append(result, alpn)
alpnSet[alpn] = struct{}{}
}
case "h3":
_, found := alpnSet[alpn]
if !found {
result = append(result, alpn)
alpnSet[alpn] = struct{}{}
}
default:
// Safe fallback: silently drop unapproved values
}
}
return result, nil
}The fix successfully mitigates both log injection and resource consumption. By explicitly restricting valid ALPN tokens to a static switch case ("h2" and "h3"), all arbitrary string conversions are eliminated. The use of alpnSet enforces a maximum slice capacity of two elements, blocking the duplicate exhaustion vector completely.
Exploitation of this vulnerability requires the attacker to control the DNS resolution path of the client using netfoil.
This can be achieved by hijacking an upstream DoH resolver, poisoning the cache of an intermediate resolver, or setting up a malicious authoritative nameserver for a domain queried by the target client.
To perform terminal escape sequence injection, the attacker crafts an HTTPS resource record where the ALPN field contains ANSI escape codes such as \x1b[2J\x1b[H (Clear Screen) or sequences designed to manipulate terminal scrollback and inject arbitrary output lines.
When the proxy resolves the target domain, the raw escape sequences are parsed and written directly to standard output by the logging routine. If the administrator views the logs in an active terminal emulator, the emulator processes the escape sequence, executing the actions locally.
For a Denial of Service attack, the attacker crafts an HTTPS resource record containing a long loop of identical or unique fake ALPN entries. The unpatched proxy continually allocates new memory for the parts slice until the host system encounters an Out of Memory (OOM) condition and kills the process.
The primary impact of this vulnerability is local denial of service and log manipulation.
Because netfoil acts as an allowlist-based DNS proxy, terminating the process disrupts local resolution entirely or bypasses security policies if fallback mechanisms are configured to permit unproxied traffic.
Log poisoning through ANSI injection presents a moderate threat to administrative integrity. It can hide security warnings, falsify system status messages, or spoof user interactions in active terminals.
This vulnerability has been assigned a CVSS score of 6.5 (Medium), reflecting the high requirement of network position or upstream control, coupled with the potential for host-level availability loss and log tampering.
Remediation requires updating the netfoil package to version v0.5.0 or later.
To update the dependency in a Go project, execute the following command:
go get -u github.com/tinfoil-factory/netfoil@v0.5.0If upgrading immediately is not feasible, administrators should enforce the use of trustworthy, verified upstream DoH resolvers (such as Cloudflare or Google DNS) that filter out malformed or suspicious resource records prior to delivery.
Additionally, standard output streams from netfoil can be sanitized through log forwarding utilities to strip control characters before they reach interactive terminal sessions.
For example, administrators can pipe log outputs through a sanitization utility:
./netfoil | tr -cd '\11\12\15\40-\176'CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
netfoil tinfoil-factory | < v0.5.0 | v0.5.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-117, CWE-20, CWE-400 |
| Attack Vector | Network (DNS Response Control Required) |
| CVSS v3.1 Score | 6.5 |
| Impact | Denial of Service, Log Manipulation |
| Exploit Status | None |
| KEV Status | Not Listed |
The software does not neutralize or incorrectly neutralizes output written to logs, allowing malicious input to alter log structures or run terminal-side payload sequences.
An issue was discovered in the tokio-postgres library for Rust prior to version 0.7.18. A trust assumption mismatch between the PostgreSQL protocol messages sent by a server and how they are parsed and indexed by the client-side library allows a rogue or compromised database server to trigger a Denial of Service (DoS) crash via an unhandled out-of-bounds slice indexing panic.
CVE-2026-14669 is a critical heap-based buffer overflow vulnerability in PostgreSQL's date/time formatting function to_char(timestamptz). The flaw arises from unsafe copying of user-controlled timezone abbreviations into a fixed-size internal buffer. An authenticated database user can trigger this issue by setting a long POSIX timezone abbreviation containing custom formatting, allowing them to overwrite adjacent heap structures and hijack execution control to achieve remote code execution (RCE) with the privileges of the 'postgres' operating system user.
An unauthenticated remote denial of service vulnerability exists in the Unleash feature management platform. By submitting a crafted JSON payload containing deeply nested structures to an OpenAPI-validated endpoint, an attacker can trigger uncontrolled recursion within the error formatting module. This leads to a call-stack exhaustion (RangeError: Maximum call stack size exceeded) inside the Node.js runtime, causing the service to crash immediately without recovery.
CVE-2026-63004 is a server-side request forgery (SSRF) vulnerability in the Unleash feature management platform. Authenticated administrators with CREATE_ADDON or UPDATE_ADDON privileges can exploit this vulnerability to initiate requests to loopback addresses, private networks, and cloud metadata endpoints, potentially leading to information disclosure and credential extraction.
Prior to version 8.0.3, Unleash's Markdown event formatter directly mutated the global template-escaping function of the shared mustache Node.js module, resulting in a process-wide security degradation where HTML/Markdown escaping was permanently disabled for the application lifetime.
A critical SQL injection vulnerability exists in the GeoTools open-source Java library. This vulnerability is situated within the post-processing phase of OGC Filter conversion inside the PostGIS DataStore module. Specifically, the `jsonArrayContains` function does not validate or sanitize its arguments before constructing PostgreSQL SQL/JSON path evaluation queries. An unauthenticated remote attacker can exploit this weakness by submitting crafted filters via standard OGC services like WFS or WMS to execute arbitrary SQL commands on the underlying database system.