Skip to content

fix(pilot-ca): validate beacon hostname to prevent path traversal#3

Merged
TeoSlayer merged 1 commit into
mainfrom
fix-issuebeacon-hostname-validation
May 28, 2026
Merged

fix(pilot-ca): validate beacon hostname to prevent path traversal#3
TeoSlayer merged 1 commit into
mainfrom
fix-issuebeacon-hostname-validation

Conversation

@TeoSlayer
Copy link
Copy Markdown
Contributor

Summary

  • issueBeacon accepted any non-empty hostname and used it directly in filepath.Join(outDir, hostname+".crt"). A hostname like evil/../host or ../escape wrote the leaf cert + key OUTSIDE outDir while still printing success — a HIGH-severity path-traversal bug.
  • Add a strict DNS-name allowlist regex (^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$) + 253-char cap, applied at the very top of issueBeacon before any filepath.Join touches outDir.
  • Rename the existing coverage test TestIssueBeacon_HostnameWithSlash_CurrentBehavior (which only logged buggy behavior) to TestIssueBeacon_HostnameWithSlash_Rejected and flip it to assert rejection + an empty outDir. Add TestIssueBeacon_HostnameWithParentDir_Rejected (covers bare .., ../escape, foo/../bar, evil\\..\\host) and TestIssueBeacon_ValidHostname_Succeeds (pins the happy path).

Test plan

  • go test -race -count=1 -timeout 120s ./... — passes
  • go vet ./... — clean
  • gofmt -l . — clean
  • All 10 TestIssueBeacon_* tests pass, including the 3 new/renamed ones
  • Existing TestIssueBeacon_RejectsEmptyHostname still passes (the validator preserves the "hostname required" error message for the empty case)

issueBeacon previously accepted any non-empty hostname and built the
output paths via filepath.Join(outDir, hostname+".crt"). A hostname
like "evil/../host" or "../escape" would write the leaf cert + key
outside outDir, silently, while still printing success. The leaf
cert itself was also malformed (invalid SAN/DNSName).

Add a strict DNS-name allowlist regex (lowercase letters, digits,
hyphen, dot only — labels <=63 chars, total <=253) and apply it at
the very top of issueBeacon, before any filepath.Join touches outDir.

Tests:
- TestIssueBeacon_HostnameWithSlash_Rejected (renamed from the
  CurrentBehavior pin) now asserts rejection + that outDir stays
  empty.
- TestIssueBeacon_HostnameWithParentDir_Rejected covers bare "..",
  "../escape", "foo/../bar", and a Windows-style "evil\\..\\host".
- TestIssueBeacon_ValidHostname_Succeeds pins the happy path on a
  normal multi-label DNS name.

All existing tests still pass under -race.
@TeoSlayer TeoSlayer merged commit d219dce into main May 28, 2026
2 checks passed
@TeoSlayer TeoSlayer deleted the fix-issuebeacon-hostname-validation branch May 28, 2026 01:23
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
main.go 80.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants