FoxIO details three TLS bugs in GoAhead web server, one rated CVSS 9.1

Sébastien Féry of FoxIO published a write-up on 26 October 2026 about three independent bugs in how GoAhead, an embedded web server, integrates with TLS libraries. GoAhead is used for device management on routers, switches, printers, gateways and industrial controls, and the post says it is deployed in hundreds of millions of devices, naming vendors such as Palo Alto Networks, Comcast, D-Link, HP, Canon, Honeywell, GE, Oracle, Siemens, Rockwell, Digi, Lockheed Martin and Boeing. That list describes where GoAhead is used; the post does not say those vendors' products are vulnerable. Each finding hits only a subset of deployments, depending on the TLS library and the settings compiled into the device.
The most severe bug, GOAHEAD-SA-2026-0006 (CVE-2026-115881, Critical, CVSS 9.1), is in the OpenSSL-compatible backend. GoAhead loads the configured certificate revocation list (CRL) into the certificate store but never sets the OpenSSL flag (X509_V_FLAG_CRL_CHECK) that turns revocation checking on, so OpenSSL returns success without consulting the list. Revoked client certificates can therefore complete the mutual TLS handshake. Because loading the file succeeds, startup gives no warning that CRL enforcement is inactive. On GoAhead 6.1.0 with OpenSSL 3.6.2, a revoked CA-signed client certificate completed the handshake with issuer verification enabled. Affected versions are GoAhead 3.4.5 through 6.1.0 with a CRL configured. The impact is clearest with client certificates required, a trusted CA bundle and issuer verification on, where a previously trusted but revoked identity keeps access. With issuer checking off, the defect remains, but unknown issuers are already accepted by policy.
The second bug, GOAHEAD-SA-2026-0005 (Medium, CVSS 5.9), is in the Mbed TLS backend. When configuring the RFC 3526 2048-bit Diffie-Hellman group, the code passes sizeof(dhm_g) as the length for both buffers, although the generator dhm_g is one byte long. The modulus dhm_p should have been 256 bytes. Mbed TLS therefore reads only the first byte of the modulus, 0xFF (255), and sends that one-byte parameter to the client in the TLS 1.2 DHE_RSA handshake. The broken parameters leave just eight possible shared-secret values (01, 02, 04, 08, 10, 20, 40 and 80 in hex). A passive observer can try each and see which decrypts the captured traffic, entirely offline. In the author's proof of concept, the shared secret was reproduced after five attempts and matched the client's. Exploitation needs a client that accepts the broken parameters. The tested OpenSSL client rejected them with a "modulus too small" error, but custom or embedded clients without a minimum-size check can complete a decryptable session. ECDHE sessions and TLS 1.3 are unaffected. Affected versions are GoAhead 4.0.2 through 6.1.0 on the Mbed TLS backend. The typo entered in 2018 during migration to the binary-parameter API and survived an April 2024 TLS refactor. Mbed TLS 4.x removed the DHE suites, so this path is not impacted there.
The third bug, GOAHEAD-SA-2026-0004 (CVE-2026-115884, High, CVSS 7.4), affects builds using LibreSSL's legacy X.509 verifier, the default for peer verification in LibreSSL 3.2.x and 3.3.2 to 3.3.6. GoAhead sets a chain-depth limit of 10 and normally rejects error 22 (chain too long). The legacy verifier's chain-building loop, which contains a FIXME comment that first drew the author to GoAhead, stops building the chain without recording the depth error. The failure reaches GoAhead as error 20 (unable to get issuer certificate locally), which the callback tolerates when issuer checking is disabled. In the demonstration, GoAhead 6.1.0 on LibreSSL 3.3.6, with client certificates required and VERIFY_ISSUER=0, accepted a 17-certificate chain rooted in an attacker-controlled self-signed CA; the handshake completed and the protected resource returned HTTP 200. The same GoAhead source built against LibreSSL 4.3.1 got error 22 at depth 10 and rejected the chain. Enabling issuer trust rejects the chain, and OpenSSL, BoringSSL, AWS-LC and LibreSSL 4.x builds are not exposed to this trigger. LibreSSL builds can inherit both this issue and the CRL defect.
The author's conclusion is that all three come down to integration details: CRL enforcement depends on a verification flag, DH parameters on buffer lengths, and chain-depth enforcement on how verification errors are handled. None of the defects prevents the affected handshake from completing. GoAhead 6.1.1 fixes the CRL check and the DH typo. The timeline: reports went to LibreSSL on 22 April, Mbed TLS on 27 April and OpenSSL on 30 April 2026; GoAhead 6.1.1 was released on 2 August; advisories were published on 12 October; the blog post followed on 26 October. Reproduction code is published in FoxIO's blog_poc repository on GitHub.
Key facts
- OpenSSL-compatible backend (GOAHEAD-SA-2026-0006, CVE-2026-115881, Critical, CVSS 9.1): the CRL is loaded but revocation checking is never enabled, so revoked client certificates complete the mTLS handshake. Affects GoAhead 3.4.5 through 6.1.0 with a CRL configured.
- Mbed TLS backend (GOAHEAD-SA-2026-0005, Medium, CVSS 5.9): a buffer-length typo cuts the 2048-bit DH modulus to one byte, leaving eight possible shared secrets. TLS 1.2 DHE_RSA sessions are decryptable if the client accepts the parameters. Affects 4.0.2 through 6.1.0.
- LibreSSL legacy verifier (GOAHEAD-SA-2026-0004, CVE-2026-115884, High, CVSS 7.4): with issuer checking off, a 17-certificate chain passed against the limit of 10 on LibreSSL 3.3.6 and the protected resource returned HTTP 200.
- GoAhead 6.1.1, released 2 August 2026, fixes the CRL check and the DH typo; advisories came out 12 October and the FoxIO post on 26 October 2026.
- The post says GoAhead is deployed in hundreds of millions of devices, but each bug affects only a subset, depending on TLS library, build and verification settings.
Why it matters
GoAhead runs the management interfaces of routers, firewalls, printers and industrial controls, and the post says it is deployed in hundreds of millions of devices. The bugs are not in the TLS libraries themselves but in how GoAhead uses them, which makes them easy to miss: the CRL bug produces no startup warning, and in all three cases the handshake still completes. The most serious one means that a client certificate an operator has revoked can still be accepted.
Who it affects
Operators and vendors of devices that embed GoAhead. The CRL bug hits GoAhead 3.4.5 through 6.1.0 on the OpenSSL-compatible backend with a CRL configured, and matters most where client certificates, a trusted CA bundle and issuer verification are all enabled. The DH bug hits 4.0.2 through 6.1.0 on Mbed TLS with TLS 1.2 DHE_RSA suites, and only when the client accepts the parameters. The depth bypass hits LibreSSL 3.2.x and 3.3.2 to 3.3.6 builds with client certificates required and issuer checking disabled. The named vendors in the post's summary are examples of GoAhead users, not confirmed vulnerable products.
How to use it
Upgrade to GoAhead 6.1.1, which checks revocation after loading the CRL and fixes the DH typo. For the LibreSSL case, the post notes that enabling issuer trust rejects the over-depth chain, and that LibreSSL 4.x builds are not exposed. To find exposure, the author suggests looking for the affected DHE suites in JA4S logs (the example fingerprint given is t120100_009f_1ca028f07214), running a query in Splunk or similar, and using JA4Scan-TLS fingerprints to map publicly facing servers to their backends. The reproduction code is in FoxIO's blog_poc repository on GitHub.
How solid is it
The post is a vendor-researcher write-up with code excerpts, callback traces and a public proof of concept. Advisories with identifiers were published on 12 October, and a fixed release has been out since 2 August. Two of the three have CVE numbers listed (CVE-2026-115884 and CVE-2026-115881). The tests cited are specific: GoAhead 6.1.0 with OpenSSL 3.6.2, LibreSSL 3.3.6 versus 4.3.1, and an OpenSSL client for the DH case. The scores and severity labels are given, but the CVSS vectors are not.
Risks and caveats
Exposure is conditional on build and configuration, and the post gives no count of vulnerable or internet-exposed devices; the hundreds-of-millions figure is GoAhead's overall deployment. The DH attack needs a permissive client, and the tested OpenSSL client rejected the parameters. The depth bypass only matters with issuer checking disabled, a setting under which self-signed certificates are already accepted. The post does not report exploitation in the wild, and it does not say whether device vendors have shipped patched firmware; it only says GoAhead 6.1.1 exists.
“None of these defects prevents the affected handshake from completing.”
— Sébastien Féry, FoxIO