---
id: "GHSA-jf74-f69g-hcj9"
page: "https://infrastack.ai/live/GHSA-jf74-f69g-hcj9"
kind: "vulnerability"
aliases: ["GHSA-jf74-f69g-hcj9"]
title: "file_server exposes private keys when the data directory falls back to ./caddy"
severity: "medium"
cvss: null
epss: null
exploited: false
status: "open"
category: "runtime"
products: [{"name": "github.com/caddyserver/caddy/v2", "fixed": ["2.11.8"], "affected": "<= 2.11.7", "ecosystem": "go"}]
ecosystems: ["go"]
tags: ["caddy", "containers", "cwe-552", "go", "runtime", "self-hosted"]
not_affected_if: ["home-directory-set", "managed-hosting", "static-dir-root"]
published_at: "2026-11-04T01:00:18+00:00"
first_seen_at: "2026-11-09T22:53:33+00:00"
updated_at: "2026-11-09T22:58:43+00:00"
sources: [{"source": "ghsa-repo", "url": "https://github.com/caddyserver/caddy/security/advisories/GHSA-jf74-f69g-hcj9", "first_seen_at": "2026-11-09T22:53:33+00:00"}]
exploit_sources: []
---

# file_server exposes private keys when the data directory falls back to ./caddy

Link for people: https://infrastack.ai/live/GHSA-jf74-f69g-hcj9 (this .md is for agents)

When neither XDG_DATA_HOME nor HOME is set, Caddy stores its certificates and private keys in a relative ./caddy folder under the working directory. A file server rooted at that directory then serves those keys to anonymous clients, letting them impersonate the site or mint trusted certificates.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- go:github.com/caddyserver/caddy/v2 affected <= 2.11.7 fixed 2.11.8

## How to check

- Run `echo $HOME $XDG_DATA_HOME` in the environment that starts Caddy; both empty means exposure is possible.
- Check whether the Caddy working directory contains a `caddy` folder with `certificates` or local CA keys.
- Check whether any `file_server` or `caddy file-server` has a root of `.` or the working directory.

## Fix

- `github.com/caddyserver/caddy/v2` fixed in `2.11.8`; affected `<= 2.11.7`.

## Timeline

- 2026-11-09T22:53:33+00:00 ghsa-repo https://github.com/caddyserver/caddy/security/advisories/GHSA-jf74-f69g-hcj9

## Documents

- [advisory] Maintainer's advisory: github.com https://github.com/caddyserver/caddy/security/advisories/GHSA-jf74-f69g-hcj9

## From the sources

### Summary

When neither `XDG_DATA_HOME` nor `HOME` is set, `caddy.AppDataDir()` returns `./caddy`, so certificates, private keys and the local CA keys live under the working directory. `caddy file-server` and any `file_server` rooted at `.` serve them to anonymous clients when started from that directory.

### Details

`AppDataDir()` (`storage.go`) falls back to the relative path `./caddy` when no home directory can be found (some containers, systemd units without a home, CI runners). `caddy file-server` serves the working directory by default (`--root` defaults to the current directory), and so does a `file_server` whose root is `.`. FrankenPHP's `php-server` command has the same default root.

Fix: `FileServer.Provision` adds the absolute form of the data directory to `Hide` when `AppDataDir()` is relative. This covers the Caddyfile, JSON configs and the `file-server` command, the same way the Caddyfile is already hidden. Patch: public PR from `dunglas:fileserver-hide-relative-data-dir`.

Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-JBWWW7FF.

### Proof of concept

```console
$ cd /srv/site && env -u HOME -u XDG_DATA_HOME caddy file-server --domain localhost
$ curl -k https://localhost/caddy/certificates/local/localhost/localhost.key
-----BEGIN EC PRIVATE KEY-----
```

The same happens with this Caddyfile, run from `/srv/site` without `HOME`:

```caddyfile
localhost {
	root .
	file_server
}
```

### Impact

Anonymous clients download TLS private keys and the local CA's root and intermediate keys, which lets them impersonate the site or mint certificates trusted by clients that installed the local CA. Only deployments without `HOME` and `XDG_DATA_HOME` that serve their working directory are affected.

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
