CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27586

Caddy Shack: How a Missing File Turns mTLS into an Open Door

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 24, 2026·6 min read·105 visits

Executive Summary (TL;DR)

If Caddy can't find your private CA file, it doesn't crash—it just lets anyone with a valid public certificate (like Let's Encrypt) log in. This high-severity bug turns a missing file into a full authentication bypass.

A critical logic error in Caddy Server's TLS module causes mutual TLS (mTLS) authentication to fail open if the configured Certificate Authority (CA) file is missing or unreadable. Instead of halting the server, Caddy swallows the error and initializes the TLS configuration with a nil CA pool, defaulting to the system's public trust store.

The Hook: The Polite Bouncer Problem

Mutual TLS (mTLS) is the gold standard for service-to-service authentication. It’s the digital equivalent of a bouncer at a speakeasy who demands a very specific membership card signed by the owner before letting you in. In a properly secured environment, if the bouncer loses the guest list, the club stays closed. Nobody gets in. That is 'failing secure'.

Caddy, the modern, automatic-HTTPS web server we all know and love, decided to take a different approach in versions prior to 2.11.1. In a twist of irony suitable for a dark comedy, if Caddy cannot find the 'guest list' (your private CA certificate), it doesn't shut down. It doesn't panic. It doesn't even throw a loud error.

Instead, it shrugs, opens the door, and decides to trust anyone with a valid ID card from anywhere. Did you lose the file containing your internal Microservices Root CA? No problem. Caddy will now happily accept a client certificate signed by DigiCert, Let's Encrypt, or any other public CA in your server's system trust store. This is the definition of 'failing open,' and for a security gateway, it is catastrophic.

The Flaw: Swallowing the Evidence

The root cause of CVE-2026-27586 isn't a buffer overflow or a complex cryptographic oracle attack. It is the bane of every senior engineer's existence: Error Swallowing.

The vulnerability resides in the ClientAuthentication.provision() method within modules/caddytls/connpolicy.go. When Caddy starts up or reloads its configuration, it attempts to load the PEM files specified in your trusted_ca_cert_file directive. These files contain the cryptographic roots of trust that define who is allowed to connect.

In the vulnerable code, the logic iterates through the file paths, attempts to convert them to DER format, and appends them to the pool. However, look at the error handling logic. If convertPEMFilesToDER returns an error (e.g., file not found, permission denied, or bad format), the function returns nil.

> [!NOTE] > In Go, returning nil as an error usually means "Success".

By returning nil when an error actually occurred, the function lies to the caller. It reports that provisioning was successful, even though the specific CA file was never loaded. The variable clientauth.ca remains uninitialized (nil), but the server startup sequence continues as if everything is fine.

The Deep Dive: Why Nil Means 'Welcome Everyone'

So, we have a nil CA pool. Why does that lead to an auth bypass instead of a handshake failure? This brings us to the behavior of Go's crypto/tls standard library, which Caddy relies on.

When Caddy configures the TLS listener, it sets ClientAuth to RequireAndVerifyClientCert. This tells the Go TLS stack: "Do not establish a connection unless the client presents a valid certificate."

However, it also sets ClientCAs to the pool we just failed to load—which is now nil. You might expect nil to mean "trust nobody." But in Go's crypto/tls implementation, if ClientCAs is nil, the library defaults to using the host system's root CA set to verify client certificates.

This means the trust boundary shifts from "Only certs signed by MySecretOrg" to "Any cert signed by a Public CA trusted by Debian/Ubuntu/Alpine." If an attacker presents a certificate for evil-hacker.com signed by Let's Encrypt, Caddy verifies the chain against the system roots, sees it's valid, and allows the connection.

The Code: The One-Line Fix

The fix is embarrassingly simple, which highlights just how dangerous silent failures are. The developers simply needed to propagate the error up the stack so the server would refuse to start.

Here is the diff from commit d42d39b4bc237c628f9a95363b28044cb7a7fe72:

// modules/caddytls/connpolicy.go
 
for _, fpath := range clientauth.TrustedCACertPEMFiles {
    ders, err := convertPEMFilesToDER(fpath)
    if err != nil {
-       return nil // The Logic Bomb
+       return err // The Fix
    }
    clientauth.TrustedCACerts = append(clientauth.TrustedCACerts, ders...)
}

They also fixed a second instance of the same bug just a few lines down where caPool.Provision(ctx) was called. If the pool provisioning failed, it previously returned nil; now it correctly returns err.

This change ensures that if your security configuration is broken (missing files), the server refuses to operate. This is the correct behavior: Fail Closed.

The Exploit: Walking Through the Open Door

Exploiting this requires no memory corruption wizardry. It purely relies on configuration drift or operator error. Here is the scenario:

  1. The Setup: A sysadmin deploys Caddy to protect an internal API. They reference /etc/caddy/private_ca.pem in the config.
  2. The Trigger: The file /etc/caddy/private_ca.pem is deleted, renamed, or has its permissions changed so the Caddy user can't read it. Maybe an automated Ansible script failed halfway through a rotation.
  3. The Reload: Caddy restarts or reloads. Due to the bug, it swallows the "File Not Found" error and starts listening.
  4. The Attack: The attacker notices the mTLS port is open.

To bypass authentication, the attacker simply needs a client certificate that validates against the server's system roots. They can generate one using any public CA (if they have a domain) or potentially use a self-signed cert if the server's system trust store is incredibly lax (unlikely, but possible in containerized dev environments).

# Attacker generates a legit cert for their own domain
# (e.g. using certbot/LetsEncrypt)
certbot certonly --standalone -d attacker-box.com
 
# Attacker connects to the victim Caddy server
curl -v --cert /etc/letsencrypt/live/attacker-box.com/cert.pem \n        --key /etc/letsencrypt/live/attacker-box.com/privkey.pem \n        https://victim-caddy-server:8443

Result: HTTP/2 200 OK. Access granted.

Mitigation: Stop the Bleeding

The remediation is straightforward. If you are running Caddy, check your version immediately.

1. Patch: Update to Caddy v2.11.1 or later. This version correctly crashes/halts if your CA files are missing.

2. Audit Your Config: Even after patching, verify that your CA files actually exist. If you update and Caddy suddenly refuses to start, congratulations—you were likely vulnerable and running in a fail-open state without realizing it.

3. Log Monitoring: In the fixed version, look for fatal errors during startup. In the vulnerable version, you won't see the error, so you must rely on auditing the filesystem to ensure the trusted_ca_cert_file paths are valid.

> [!WARNING] > Do not rely on "it works" as a sign of security. In this specific case, "it works" was the symptom of the vulnerability.

Official Patches

Caddy ServerFix commit implementing error propagation

Fix Analysis (1)

Technical Appendix

CVSS Score
8.8/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:P

Affected Systems

Caddy Server (Go implementation)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Caddy
caddyserver
< 2.11.12.11.1
AttributeDetail
CWE IDCWE-755
Attack VectorNetwork
CVSS v4.08.8 (High)
ImpactAuthentication Bypass
Root CauseImproper Error Handling (Swallowed Error)
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1553Subvert Trust Controls
Defense Evasion
T1078Valid Accounts
Initial Access
CWE-755
Improper Handling of Exceptional Conditions

Improper Handling of Exceptional Conditions

Known Exploits & Detection

GitHub GistProof of Concept Go test case demonstrating the fail-open behavior

Vulnerability Timeline

PoC Discovered by researcher moscowchill
2026-02-09
Vendor patched (Commit d42d39b)
2026-02-12
CVE-2026-27586 Published
2026-02-24

References & Sources

  • [1]GHSA-hffm-g8v7-wrv7
  • [2]NVD - CVE-2026-27586

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•5 minutes ago•CVE-2026-105698
5.4

CVE-2026-105698: Missing Authorization in Deprecated Chat Vertices Endpoints in Langflow

A missing authorization vulnerability in Langflow versions 1.0.0 through 1.10.0 allows authenticated users (and unauthenticated users in versions prior to 1.7.2) to access private workflow structures and execute graph components by targeting deprecated API endpoints.

Amit Schendel
Amit Schendel
0 views•8 min read
•about 1 hour ago•CVE-2026-105697
9.9

CVE-2026-105697: OS Command Injection in Langflow Model Context Protocol Integration

A critical OS command injection vulnerability exists in Langflow's Model Context Protocol (MCP) server integration using stdio transport, allowing unauthenticated remote command execution under default configurations.

Alon Barad
Alon Barad
5 views•5 min read
•about 2 hours ago•CVE-2026-105745
6.7

CVE-2026-105745: Arbitrary Code Execution via Malicious Entrypoint Discovery in Docling base_factory

Docling prior to version 2.131.0 is vulnerable to arbitrary local code execution during module initialization due to incorrect order of operations in its plugin discovery system. Even when the default option to reject external plugins is active, Docling utilizes Pluggy to scan and import entrypoints before performing namespace validation.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 3 hours ago•CVE-2026-105749
6.5

CVE-2026-105749: Unbounded Table Attributes in Docling Backends Leads to Resource Exhaustion

An uncontrolled resource consumption vulnerability exists in the Docling document conversion library. Maliciously structured HTML, JATS, ODS, or BoxNote inputs containing table cells with excessively large 'rowspan' or 'colspan' attribute values trigger algorithmic complexity conditions. This allows unauthenticated remote attackers to initiate resource exhaustion states, crashing or hanging the target document processing pipeline while bypassing configured timeouts.

Amit Schendel
Amit Schendel
9 views•6 min read
•about 4 hours ago•CVE-2026-105748
4.3

CVE-2026-105748: Local File Inclusion and Arbitrary File Disclosure in Docling Document Parser

A Local File Inclusion (LFI) and Arbitrary File Disclosure vulnerability exists in Docling and Docling Slim versions >= 2.16.0 up to 2.131.0. When parsing serialized DoclingDocument structures using the JSON input format, the backend fails to restrict image URI schemes, allowing remote attackers to retrieve local files and verify path existence on the host system during embedded document export.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 5 hours ago•CVE-2026-105744
7.5

CVE-2026-105744: Arbitrary File Read and Remote Code Execution in Docling Tectonic Engine

Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.

Amit Schendel
Amit Schendel
8 views•7 min read