serve.go: validate URL-derived domain (defense in depth, Windows considerations) #38

Open
opened 2026-05-20 21:48:42 +02:00 by heiko · 1 comment
Owner

Follow-up from #31 / PR #37. User confirmed filing in the working session.

The CN from the X.509 subject is now validated in cnList via list.ValidateClientName (PR #37). The other attacker-controlled string used as a filename — the URL-derived domain in serve.go — is not, and currently relies on layered defenses:

  • strings.Split on req.URL.Path with / prevents parts[3] from containing /
  • http.Dir.Open rejects "..", so .. traversal fails
  • http.Dir.Open on Windows additionally rejects paths containing the OS separator \

Today the combination is sufficient. The concern is brittleness: any of these defenses could be lost in a refactor (e.g. switching to http.ServeMux PathValue or net/url RawPath handling), and the validator gap would silently re-open the same class of bug as #31.

Proposed change

Validate domain with list.ValidateDomain in serve.go right after extraction, covering /v1/cert, /v1/chain, /v1/fullchain, /v1/privkey, /v1/bundle.

ValidateClientName (introduced in #37) is too strict here — it rejects * which is needed for wildcard certs retrievable by URL (/v1/cert/*.example.com). ValidateDomain is the right choice for the URL-derived domain.

Windows-specific considerations

Official builds target linux/amd64 and linux/arm64 via gogogo, but go build on Windows works:

  • http.Dir.Open rejects \ in names (filepath.Separator != '/' branch). Today no \-traversal even without validation.
  • Whether Windows reserved names (CON, NUL, ...) should be rejected up-front for the URL-derived domain is a behaviour question, not a security one — the OS-layer open would fail anyway. Symmetry with the cnList side argues for a shared validator.

Why low priority

No live exploit vector identified on Linux or Windows. Hardening against a refactor that might re-open the door.

  • #31 — original CN traversal bug
  • #37 — server cnList fix (introduces ValidateClientName)
  • #39 — adjacent client-side surface (cmd/cert-proxy-client/ uses ValidateDomain for paths)

(co)authored by ai (claude-opus-4-7)

Follow-up from #31 / PR #37. User confirmed filing in the working session. The CN from the X.509 subject is now validated in cnList via list.ValidateClientName (PR #37). The other attacker-controlled string used as a filename — the URL-derived domain in serve.go — is not, and currently relies on layered defenses: - strings.Split on req.URL.Path with / prevents parts[3] from containing / - http.Dir.Open rejects "..", so .. traversal fails - http.Dir.Open on Windows additionally rejects paths containing the OS separator \\ Today the combination is sufficient. The concern is brittleness: any of these defenses could be lost in a refactor (e.g. switching to http.ServeMux PathValue or net/url RawPath handling), and the validator gap would silently re-open the same class of bug as #31. ## Proposed change Validate domain with list.ValidateDomain in serve.go right after extraction, covering /v1/cert, /v1/chain, /v1/fullchain, /v1/privkey, /v1/bundle. ValidateClientName (introduced in #37) is too strict here — it rejects * which is needed for wildcard certs retrievable by URL (/v1/cert/*.example.com). ValidateDomain is the right choice for the URL-derived domain. ## Windows-specific considerations Official builds target linux/amd64 and linux/arm64 via gogogo, but go build on Windows works: - http.Dir.Open rejects \\ in names (filepath.Separator != '/' branch). Today no \\-traversal even without validation. - Whether Windows reserved names (CON, NUL, ...) should be rejected up-front for the URL-derived domain is a behaviour question, not a security one — the OS-layer open would fail anyway. Symmetry with the cnList side argues for a shared validator. ## Why low priority No live exploit vector identified on Linux or Windows. Hardening against a refactor that might re-open the door. ## Related - #31 — original CN traversal bug - #37 — server cnList fix (introduces ValidateClientName) - #39 — adjacent client-side surface (cmd/cert-proxy-client/ uses ValidateDomain for paths) (co)authored by ai (claude-opus-4-7)
Author
Owner

AI attribution comment added per repository instruction for this open issue.\n\n(co)authored by ai:gpt-5-codex

AI attribution comment added per repository instruction for this open issue.\n\n(co)authored by ai:gpt-5-codex
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
heiko/cert-proxy#38
No description provided.