Your Reverse Proxy Might Be Your Biggest Security Hole: Caddy's 5-CVE Wake-Up Call


⚡ TL;DR

On February 24, 2026, the Caddy web server project disclosed five security vulnerabilities — including two rated CRITICAL (CVSS 9.1) — affecting all versions prior to v2.11.1. The vulnerabilities include a silent mTLS fail-open flaw that accepts any client certificate when a CA file is misconfigured, an admin API CSRF that lets a malicious webpage silently overwrite your running server config, two separate path-bypass ACL flaws, and a FrankenPHP RCE via Unicode case-folding confusion in the FastCGI layer. If you run Caddy as a reverse proxy, TLS terminator, or PHP gateway — upgrade to v2.11.1 immediately. There is no workaround for the two critical flaws short of patching.​‌‌​​​‌‌‍​‌‌​​​​‌‍​‌‌​​‌​​‍​‌‌​​‌​​‍​‌‌‌‌​​‌‍​​‌​‌‌​‌‍​‌‌‌​​‌​‍​‌‌​​‌​‌‍​‌‌‌​‌‌​‍​‌‌​​‌​‌‍​‌‌‌​​‌​‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​​‌​‌‌​‌‍​‌‌‌​​​​‍​‌‌‌​​‌​‍​‌‌​‌‌‌‌‍​‌‌‌‌​​​‍​‌‌‌‌​​‌‍​​‌​‌‌​‌‍​‌‌​​​‌‌‍​‌‌‌​‌‌​‍​‌‌​​‌​‌‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​‌‌​​​‌‌‍​‌‌‌​‌​‌‍​‌‌‌​​‌​‍​‌‌​‌​​‌‍​‌‌‌​‌​​‍​‌‌‌‌​​‌‍​​‌​‌‌​‌‍​‌‌‌​‌‌​‍​‌‌‌​‌​‌‍​‌‌​‌‌​​‍​‌‌​‌‌‌​‍​‌‌​​‌​‌‍​‌‌‌​​‌​‍​‌‌​​​​‌‍​‌‌​​​‌​‍​‌‌​‌​​‌‍​‌‌​‌‌​​‍​‌‌​‌​​‌‍​‌‌‌​‌​​‍​‌‌​‌​​‌‍​‌‌​​‌​‌‍​‌‌‌​​‌‌‍​​‌​‌‌​‌‍​​‌‌​​‌​‍​​‌‌​​​​‍​​‌‌​​‌​‍​​‌‌​‌‌​


The Proxy in Front of Everything

Modern infrastructure puts reverse proxies at the front of almost everything. They handle TLS termination, authentication offloading, load balancing, and access control. Caddy has become a popular choice precisely because it promised to make this easy: automatic HTTPS, a clean config syntax, and a powerful module system. As of 2026, Caddy is widely deployed in containerised environments, homelab setups, and production microservice architectures worldwide.

That "easy security" promise is exactly what makes this week's disclosure so alarming. When your reverse proxy is configured to enforce mutual TLS authentication — and silently stops enforcing it due to a swallowed error — every service sitting behind it is exposed. When a webpag

e can CSRF-attack your local admin endpoint and rewrite your server config, your security model collapses. Five CVEs disclosed simultaneously on February 24, 2026, paint a picture of a trust boundary that was thinner than anyone realised.​‌‌​​​‌‌‍​‌‌​​​​‌‍​‌‌​​‌​​‍​‌‌​​‌​​‍​‌‌‌‌​​‌‍​​‌​‌‌​‌‍​‌‌‌​​‌​‍​‌‌​​‌​‌‍​‌‌‌​‌‌​‍​‌‌​​‌​‌‍​‌‌‌​​‌​‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​​‌​‌‌​‌‍​‌‌‌​​​​‍​‌‌‌​​‌​‍​‌‌​‌‌‌‌‍​‌‌‌‌​​​‍​‌‌‌‌​​‌‍​​‌​‌‌​‌‍​‌‌​​​‌‌‍​‌‌‌​‌‌​‍​‌‌​​‌​‌‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​‌‌​​​‌‌‍​‌‌‌​‌​‌‍​‌‌‌​​‌​‍​‌‌​‌​​‌‍​‌‌‌​‌​​‍​‌‌‌‌​​‌‍​​‌​‌‌​‌‍​‌‌‌​‌‌​‍​‌‌‌​‌​‌‍​‌‌​‌‌​​‍​‌‌​‌‌‌​‍​‌‌​​‌​‌‍​‌‌‌​​‌​‍​‌‌​​​​‌‍​‌‌​​​‌​‍​‌‌​‌​​‌‍​‌‌​‌‌​​‍​‌‌​‌​​‌‍​‌‌‌​‌​​‍​‌‌​‌​​‌‍​‌‌​​‌​‌‍​‌‌‌​​‌‌‍​​‌​‌‌​‌‍​​‌‌​​‌​‍​​‌‌​​​​‍​​‌‌​​‌​‍​​‌‌​‌‌​

This post covers every vulnerability, what it means in plain terms, who is at risk, and exactly what to do about it.


The Five Vulnerabilities at a Glance

CVE Component Severity CVSS Summary
CVE-2026-27586 TLS / mTLS CRITICAL 9.1 mTLS fails open when CA cert file is missing or malformed
CVE-2026-27589 Admin API CRITICAL 9.1 CSRF allows remote config replacement via /load endpoint
CVE-2026-27585 File matcher High 7.5 Backslash injection bypasses path-based ACLs
CVE-2026-27587 HTTP matcher High 7.5 Percent-encoded characters bypass case-insensitive ACL matchers
CVE-2026-27590 FastCGI / FrankenPHP High 8.1 Unicode case-folding causes incorrect path split → PHP RCE

All five were fixed in Caddy v2.11.1, released February 24, 2026 [1].


CVE-2026-27586: mTLS Fail-Open (CRITICAL, CVSS 9.1)

What happened

Mutual TLS (mTLS) is an authentication scheme where both the server and the client present certificates signed by a trusted Certificate Authority (CA). It's used to ensure that only authorised clients — machines, microservices, or users with specific certificates — can connect. The entire security guarantee rests on the CA file being correctly loaded and trusted.

In Caddy's ClientAuthentication.provision() function inside the TLS module, two errors are silently swallowed. If the configured CA certificate file is missing, unreadable, or malformed, Caddy does not abort startup or log a fatal error. Instead, it starts successfully — but with mTLS effectively disabled. The server then accepts any client certificate signed by any system-trusted CA, completely bypassing the intended private CA trust boundary [2].

The vulnerability was reported on February 24, 2026 [2], and a proof-of-concept demonstrating the fail-open behaviour was published publicly [3].

ELI10 Explanation

Imagine you're a bouncer at a club. Your job is to only let in people who show a special VIP card signed by your club's printer. But someone accidentally shredded the list of what your club's VIP cards look like. Instead of closing the door, you just… let everyone in who shows any card at all — even a card from a completely different club. That's what Caddy was doing when the CA file was missing. The lock was there, but it wasn't actually locking anything.

Who is at risk

Any Caddy deployment that uses client_auth with a trusted_ca_certs_pem_file or similar configuration directive to enforce mTLS. This is common in:

  • Zero-trust architectures using service-mesh patterns
  • Internal APIs exposed through Caddy with mTLS as the sole authentication mechanism
  • Any setup where Caddy is the "sidecar security" layer — handling auth so the backend doesn't have to

If you configured mTLS and assumed Caddy was enforcing it, you may have been running with no client authentication at all — potentially for as long as you've been on an affected version.


CVE-2026-27589: Admin API CSRF — Localhost Is Not Safe (CRITICAL, CVSS 9.1)

What happened

Caddy ships with a local admin API that listens by default on 127.0.0.1:2019. This API exposes a POST /load endpoint that replaces the entire running configuration of the server with whatever JSON body is submitted. This is a powerful feature for dynamic config management — and a significant attack surface if not properly guarded.

When enforce_origin is not explicitly enabled in Caddy's admin configuration, the /load endpoint accepts cross-origin requests. This means a webpage served by an attacker — visited by anyone on the same machine running Caddy — can issue a POST /load request via a browser and silently overwrite the running server configuration. The attacker can change the admin listener settings, alter HTTP routing, disable TLS, add new routes, or redirect traffic [4].

This is a classic Cross-Site Request Forgery (CSRF) attack. The browser's same-origin policy does not protect localhost endpoints from cross-origin POST requests in all browsers, particularly when Content-Type: text/plain or application/x-www-form-urlencoded is used.

ELI10 Explanation

Imagine you left your house's control panel (lights, locks, security) accessible from inside the house, and your front door has a mail slot. A bad actor slides a note through the mail slot that says "hey control panel, turn off all the locks and open all the windows." If no one is watching, the control panel just does it. That's this vulnerability. The admin panel was inside your house (localhost), but a website you visited could still slip instructions through the mail slot (your browser) and reconfigure everything.

Who is at risk

Any deployment where:

  • Caddy is running on a machine with a web browser (developer workstations, single-server setups)
  • The admin API is not explicitly locked down with enforce_origin: true
  • An attacker can trick someone on the machine to visit a malicious website

This is especially dangerous in shared hosting environments or workstation-based Caddy instances.


CVE-2026-27585: Backslash Blues — One Character Bypasses Your ACLs (High, CVSS 7.5)

What happened

Caddy's file server module uses a "file matcher" to restrict which paths can be accessed. This is commonly used to block access to sensitive directories or enforce allow-lists. The path sanitisation logic in matcher.go correctly handles forward slashes but does not sanitise backslashes (\) in the request URI [5].

On Unix-like systems, file paths use forward slashes and backslashes are typically treated as literal characters in URLs — but Caddy's glob-matching logic passes paths through Go's filepath package, which on some systems normalises backslashes into directory separators. The result is a semantic gap: a request to /admin\.. might not match the ACL rule protecting /admin/ but does access the same underlying filesystem location.

The fix (landed in v2.11.1) sanitises backslashes before applying the file matcher glob logic [5].

ELI10 Explanation

Think of your Caddy rules as a velvet rope that says "nobody gets into the VIP section called /admin/." A clever visitor tries going in through a door labelled /admin\ with a backslash instead of a forward slash. The bouncer checks the list, doesn't see that exact name, and waves them through — even though it's the same room. One weird character, and the whole rope is useless.


CVE-2026-27587: Bypassing ACLs with Percent-Encoding (High, CVSS 7.5)

What happened

Caddy's HTTP request matchers use case-insensitive comparisons for path matching in some configurations. When a path matcher includes percent-encoded characters (e.g., %2F for /), Caddy's internal normalisation and case-folding logic short-circuits in a way that causes the matcher to evaluate a different effective path than the one being accessed [6].

Specifically, if a security rule is expressed with a path that contains percent-encoded segments, an attacker can craft a request where the decoded/normalised form matches the protected resource but the raw form passes the matcher's check. This allows bypassing access controls entirely, silently routing the request to a protected backend handler without triggering any configured security rules.

ELI10 Explanation

URLs have a secret language: %41 means the letter A, %2F means /. Most of the time everything works fine. But Caddy's security checks were reading the secret language version while the actual file system was reading the plain version. It's like having a bouncer who only speaks one language checking IDs written in another — they can't tell you're trying to sneak into the VIP area if the name on your ID looks different in their language.


CVE-2026-27590: FrankenPHP RCE via Unicode Case-Folding (High, CVSS 8.1)

What happened

This is the most technically complex of the five, and arguably the scariest for anyone running PHP via Caddy + FrankenPHP.

Caddy's FastCGI transport layer — used to proxy requests to PHP-FPM or the embedded FrankenPHP runtime — uses a split_path configuration to separate the PHP script path from the PATH_INFO. For example, /app/index.php/extra-info should resolve SCRIPT_FILENAME to /app/index.php and PATH_INFO to /extra-info.

The bug: Caddy computes the split index by calling strings.ToLower() on a copy of the request path, finds where .php appears in that lowercased copy, then uses that byte offset to slice the original path. This is unsafe for Unicode. Some Unicode characters, when lowercased via Go's strings.ToLower(), expand in byte length (e.g., the Turkish dotless-i ı maps to i but their UTF-8 encodings differ in length). An attacker can craft a path containing such characters before the .php extension so that the byte offset computed on the lowercased copy points to a different location in the original string [7].

The result: Caddy sends the wrong SCRIPT_FILENAME to PHP. In deployments where an attacker can upload arbitrary files (images, documents), they can trick FrankenPHP into executing a non-.php file as a PHP script — achieving Remote Code Execution [7].

ELI10 Explanation

Imagine you're a librarian (Caddy) looking for a book called "photo.php" on the shelf. You translate the title to lowercase to search the index, find the right shelf number, then walk to that shelf. But in the translation, the words shifted slightly — so you end up at shelf number 42 instead of shelf 41. Instead of the book you wanted, you grab the book sitting at shelf 42: a photo someone uploaded. Now the printer (PHP) prints that photo file as if it were a programme. If that photo secretly contains PHP code, it runs — and the attacker now controls your server.

This is a classic "confused deputy" attack enabled by a subtle Unicode encoding assumption.


Why This Cluster of Vulnerabilities Is a Wake-Up Call

These five CVEs share a common theme that goes beyond any single bug: the proxy is trusted too much, and that trust is invisible.

Modern DevOps teams love the "sidecar security" pattern. Instead of baking authentication and access control into every microservice, you offload it to the reverse proxy layer. Caddy validates client certs. Caddy enforces path restrictions. Caddy terminates TLS. The backend services don't worry about it — they just trust that if a request reached them, it was authorised.

CVE-2026-27586 breaks that pattern silently. You configured mTLS, you checked the box, your security audit passed — but the CA file had a whitespace issue on one deploy, and Caddy silently stopped enforcing authentication. No log entry. No alert. No failed health check. Just an open door.

The backslash and percent-encoding bypasses (CVE-2026-27585, CVE-2026-27587) demonstrate the fundamental challenge of implementing access control at the URL layer: the same resource can be addressed by an enormous variety of syntactically different paths. Every normalisation step is an opportunity for a gap between what the security layer sees and what the filesystem or backend actually receives. This is the same class of vulnerability that has plagued web servers for decades — from the famous IIS Unicode directory traversal of 2001 to modern framework path-traversal bugs.

The admin CSRF (CVE-2026-27589) is a reminder that "localhost" is not a security boundary. Browser same-origin policy has always had edge cases around 127.0.0.1, and any unauthenticated state-changing API reachable from a browser is a CSRF risk. The Caddy team's fix — enabling enforce_origin by default in v2.11.1 — is the right approach, but it required a CVE to get there.


How to Check If You Are Affected

Step 1: Check your Caddy version

caddy version

If the output shows anything earlier than v2.11.1, you are affected by all five vulnerabilities.

Step 2: Check for mTLS usage

Search your Caddyfile or JSON config for client_auth, trusted_ca_certs, or trusted_ca_certs_pem_file. If any of these appear, you may have been running without effective client authentication.

Step 3: Check admin API exposure

Look for admin blocks in your config. Check if enforce_origin is set. If you run Caddy on a workstation or shared machine, treat any unpatched version as compromised.

Step 4: Check for FrankenPHP / FastCGI usage

If you use php_fastcgi or FrankenPHP in your Caddyfile, you are potentially affected by CVE-2026-27590 — especially if users can upload files.


Remediation: Upgrade to Caddy v2.11.1

The fix is straightforward: upgrade to Caddy v2.11.1.

# If installed via the official Caddy package repository
sudo apt upgrade caddy  # Debian/Ubuntu
sudo dnf upgrade caddy  # Fedora/RHEL

# If using the official binary
curl -L https://github.com/caddyserver/caddy/releases/latest/download/caddy_linux_amd64 -o /usr/local/bin/caddy
chmod +x /usr/local/bin/caddy
caddy version

# If using Docker
docker pull caddy:2.11.1

After upgrading, explicitly audit your mTLS configurations. Even with v2.11.1, verify that your CA cert files are present, readable, and correctly formatted on every deploy. Add startup health checks that validate certificate loading. Don't trust the "server started" log entry alone.

For the admin API, explicitly configure enforce_origin in your admin block:

{
  admin localhost:2019 {
    enforce_origin
    origins localhost:2019
  }
}

If you don't use the admin API at all, disable it entirely:

{
  admin off
}

Defence in Depth: Lessons Beyond Patching

Patching is mandatory, but these CVEs reveal structural risks worth addressing at the architecture level.

Don't rely on a single security boundary. If your backend services assume that all requests arriving from Caddy are pre-authenticated, a single proxy misconfiguration exposes everything. Backend services should perform at least minimal authentication validation independently.

Log everything at the TLS boundary. A proper mTLS implementation should log every TLS handshake, including the presented client certificate's subject and issuer. If CVE-2026-27586 had been active on your system, you'd have seen client connections succeeding without the expected CA chain — if you were logging it.

Treat your proxy config as code. Version control your Caddyfile. Run CI checks against it. Diff it on every deploy. Config drift — like a CA cert file going missing on one node — is one of the leading causes of silent security regressions.

Subscribe to security advisories. The Caddy project publishes security advisories via GitHub at github.com/caddyserver/caddy/security/advisories. Subscribe so you're notified the day an advisory drops, not when it hits the news cycle.

Container image pinning. If you're running Caddy in Docker or Kubernetes, pin your image tags to specific digest hashes rather than floating tags like caddy:latest. This gives you explicit control over when you upgrade and lets you audit the change.


Are You Exposed? Get a Free Assessment

If you run Caddy in production and aren't sure whether your configuration is affected — or if you want an expert eye on your reverse proxy architecture — lilMONSTER offers a free 30-minute security consultation.

We help businesses of all sizes understand their real attack surface, not just the CVE checklist. Whether you're a solo developer who deployed Caddy on a VPS, or a team running a microservice mesh with mTLS everywhere, we can help you verify your posture and prioritise what actually matters.

Book a free consult → consult.lil.business

No sales pitch. No obligation. Just clarity.


Frequently Asked Questions

Q: I use Caddy but not mTLS. Am I still at risk?

Yes. CVE-2026-27589 (admin API CSRF) affects all Caddy deployments that have not explicitly disabled or locked down the admin API. CVE-2026-27585 and CVE-2026-27587 (path bypass) affect anyone using path-based access controls in their Caddyfile. Upgrade to v2.11.1 regardless of whether you use mTLS.

Q: Does this affect the Caddy Docker image?

Yes. The official Caddy Docker images prior to the v2.11.1 tag are affected. Pull caddy:2.11.1 or caddy:latest (which should now point to v2.11.1) and redeploy.

Q: I use FrankenPHP but users can't upload files. Is CVE-2026-27590 still a risk?

The RCE scenario for CVE-2026-27590 requires an attacker to control a file on disk that gets executed as PHP. Without file upload capability, the practical RCE risk is lower — but the path confusion issue still exists, and there may be edge cases in your deployment. Upgrade regardless. The path split bug can cause unexpected behaviour even without full RCE.

Q: Can I detect if CVE-2026-27586 was exploited?

This is the hard question. Because the fail-open was silent — no log entry, no error — you cannot definitively confirm exploitation from Caddy logs alone. Review your TLS access logs for client connections that should have failed mTLS validation. If your backend services log client certificate information, cross-reference that. If you don't have those logs, assume the worst and treat the exposed services as potentially compromised during the window between your last known-good deploy and patching.

Q: Is there a CVSSv3 score published by NIST for these CVEs?

All five CVEs were published to the NIST National Vulnerability Database (NVD) on or around February 24, 2026. The two critical CVEs (CVE-2026-27586 and CVE-2026-27589) carry a CVSS v3.1 base score of 9.1. CVE-2026-27590 carries 8.1. CVE-2026-27585 and CVE-2026-27587 are rated 7.5. Check the NVD entries directly for the authoritative scores [8].

Q: Why are so many Caddy vulnerabilities appearing at once?

It appears these vulnerabilities were discovered as part of a coordinated security audit. Batch disclosure is common after security researchers perform a focused review of a single codebase. The simultaneous disclosure does not necessarily mean Caddy is uniquely insecure compared to other web servers — all complex software has vulnerabilities. What matters is the response: a patch was released the same day as disclosure, which is commendable.

Q: How do I know if the admin API CSRF (CVE-2026-27589) was exploited?

Check your Caddy admin API access logs if you have them. More practically: compare your current running configuration against your version-controlled Caddyfile. If they differ in unexpected ways, treat this as a red flag. After patching, enable enforce_origin and audit your config immediately.


FAQ

Q: What is the main security concern covered in this post? A:

Q: Who is affected by this? A:

Q: What should I do right now? A:

Q: Is there a workaround if I can't patch immediately? A:

Q: Where can I learn more? A:

References

[1] Caddy Project, "Caddy v2.11.1 Release Notes," GitHub, Feb. 24, 2026. [Online]. Available: https://github.com/caddyserver/caddy/releases/tag/v2.11.1

[2] National Institute of Standards and Technology, "CVE-2026-27586: Caddy mTLS Client Authentication Silently Fails Open," NVD, Feb. 24, 2026. [Online]. Available: https://nvd.nist.gov/vuln/detail/CVE-2026-27586

[3] moscowchill, "PoC test: mTLS fail-open due to swallowed errors in Caddy connpolicy.go," GitHub Gist, Feb. 2026. [Online]. Available: https://gist.github.com/moscowchill/9566c79c76c0b64c57f8bd0716f97c48

[4] National Institute of Standards and Technology, "CVE-2026-27589: Caddy Cross-Origin Config Application via Local Admin API /load," NVD, Feb. 24, 2026. [Online]. Available: https://nvd.nist.gov/vuln/detail/CVE-2026-27589

[5] Caddy Project, "GHSA-4xrr-hq4w-6vf4: Improper Sanitization of Glob Characters in File Matcher," GitHub Security Advisory, Feb. 24, 2026. [Online]. Available: https://github.com/caddyserver/caddy/security/advisories/GHSA-4xrr-hq4w-6vf4

[6] Caddy Project, "GHSA: Caddy HTTP Matcher Percent-Encoding ACL Bypass," GitHub Security Advisory, Feb. 24, 2026. [Online]. Available: https://github.com/caddyserver/caddy/security/advisories

[7] Caddy Project, "GHSA-5r3v-vc8m-m96g: Unicode Case-Folding Length Expansion in FastCGI Transport," GitHub Security Advisory, Feb. 24, 2026. [Online]. Available: https://github.com/caddyserver/caddy/security/advisories/GHSA-5r3v-vc8m-m96g

[8] National Institute of Standards and Technology, "National Vulnerability Database — Caddy Server Advisories," NVD, Feb. 2026. [Online]. Available: https://nvd.nist.gov/vuln/search/results?query=caddy&results_type=overview

[9] MITRE Corporation, "Common Vulnerabilities and Exposures — CVE-2026-27586," MITRE CVE, Feb. 2026. [Online]. Available: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-27586

[10] GitLab Security Research, "CVE-2026-27586: Caddy mTLS Client Authentication Advisory," GitLab Advisories, Feb. 24, 2026. [Online]. Available: https://advisories.gitlab.com/pkg/golang/github.com/caddyserver/caddy/v2/modules/caddytls/CVE-2026-27586/

[11] GitLab Security Research, "CVE-2026-27589: Caddy Cross-Origin Admin API Advisory," GitLab Advisories, Feb. 24, 2026. [Online]. Available: https://advisories.gitlab.com/pkg/golang/github.com/caddyserver/caddy/v2/CVE-2026-27589/

[12] GitLab Security Research, "CVE-2026-27590: Caddy FastCGI Unicode Case-Folding Advisory," GitLab Advisories, Feb. 24, 2026. [Online]. Available: https://advisories.gitlab.com/pkg/golang/github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy/fastcgi/CVE-2026-27590/


This article was produced by lilMONSTER — cybersecurity consulting for modern infrastructure. Nothing in this post constitutes legal or compliance advice. Always verify CVE details against official NVD and vendor advisory sources before taking action.

Found an error? Got a question? Reach out via the consult form — we read every submission.

Ready to strengthen your security?

Talk to lilMONSTER. We assess your risks, build the tools, and stay with you after the engagement ends. No clipboard-and-leave consulting.

Get a Free Consultation