Create domain verification system #10

Closed
opened 2025-12-03 23:17:08 +00:00 by ric · 1 comment
Owner

Custom domains in .pages files should be verified by DNS TXT records. If a page has a custom domain of test.squarecows.com then the user should create a record in DNS of TXT test.squarecows.com and the value should be a hash of the full repository name. If the DNS record does not match the DNS TXT value it will not be added as a custom domain mapping. This will prevent a malicious user taking over the sites by creating lots of repositories. This feature should be enabled by the admins with a setting in the middlewares.yml file for Traefik.

Custom domains in .pages files should be verified by DNS TXT records. If a page has a custom domain of test.squarecows.com then the user should create a record in DNS of TXT test.squarecows.com and the value should be a hash of the full repository name. If the DNS record does not match the DNS TXT value it will not be added as a custom domain mapping. This will prevent a malicious user taking over the sites by creating lots of repositories. This feature should be enabled by the admins with a setting in the middlewares.yml file for Traefik.
ric added this to the Roadmap project 2025-12-03 23:17:17 +00:00
ric self-assigned this 2025-12-03 23:17:19 +00:00
ric added this to the 0.1.x release milestone 2025-12-03 23:37:48 +00:00
Author
Owner

Implementation Complete

DNS TXT record verification for custom domains has been implemented on branch 0.1.0.

Implementation Summary

Security Feature: Prevents malicious users from hijacking custom domains by requiring DNS TXT record verification before registering custom domain mappings.

How It Works

  1. Configuration: Admin enables DNS verification in Traefik middleware config:

    enableCustomDomainDNSVerification: true
    
  2. DNS TXT Record Format:

    TXT <custom-domain> bovine-pages-verification=<SHA256_HASH>
    

    Where <SHA256_HASH> is the SHA256 hash of owner/repository

  3. Verification Process:

    • When a .pages file specifies a custom domain
    • Plugin performs DNS TXT lookup on the domain
    • Compares TXT record value with expected hash (using constant-time comparison to prevent timing attacks)
    • Only registers domain mapping if verification succeeds

Example

For repository squarecows/bovine-website with custom domain bovine.squarecows.com:

  1. Generate hash:

    ./examples/generate-dns-verification-hash.sh squarecows bovine-website
    # Output: 73bb8214899661e7f7900c77714586cc51702e6cf26a58c62e17fa9d88f3d3d3
    
  2. Add DNS TXT record:

    TXT bovine.squarecows.com bovine-pages-verification=73bb8214899661e7f7900c77714586cc51702e6cf26a58c62e17fa9d88f3d3d3
    
  3. Add to .pages file:

    enabled: true
    custom_domain: bovine.squarecows.com
    
  4. Activate: Visit https://squarecows.pages.example.com/bovine-website to register (DNS verification will be performed automatically)

Features

Security:

  • SHA256 hashing of repository identifier
  • Timing attack prevention with crypto/subtle.ConstantTimeCompare
  • Proof of domain ownership required

Admin Control:

  • Opt-in configuration (disabled by default)
  • No breaking changes for existing deployments

Usability:

  • Helper script to generate verification hashes
  • Clear error messages in logs
  • Comprehensive documentation

Quality:

  • Uses only Go standard library (Yaegi compatible)
  • 8 comprehensive DNS verification tests
  • All 59 non-Redis tests passing
  • Full documentation in README

Files Changed

  • pages.go - Core verification logic
  • dns_verification_test.go - Test suite (new file)
  • examples/generate-dns-verification-hash.sh - Helper script (new file)
  • README.md - Complete documentation
  • CHANGELOG.md - Feature documentation

Configuration Reference

http:
  middlewares:
    pages-server:
      plugin:
        pages-server:
          pagesDomain: pages.example.com
          forgejoHost: https://git.example.com
          # Enable DNS verification for custom domains
          enableCustomDomainDNSVerification: true

Documentation

Complete setup guide, troubleshooting, and examples available in:

  • README.md "DNS Verification for Custom Domains" section
  • Helper script: examples/generate-dns-verification-hash.sh

Branch

Feature available on branch: 0.1.0
Will be included in version 0.1.0 release

Testing

To test locally:

git checkout 0.1.0
go test -v -run TestDNS
# All DNS verification tests pass
## ✅ Implementation Complete DNS TXT record verification for custom domains has been implemented on branch `0.1.0`. ### Implementation Summary **Security Feature:** Prevents malicious users from hijacking custom domains by requiring DNS TXT record verification before registering custom domain mappings. ### How It Works 1. **Configuration:** Admin enables DNS verification in Traefik middleware config: ```yaml enableCustomDomainDNSVerification: true ``` 2. **DNS TXT Record Format:** ``` TXT <custom-domain> bovine-pages-verification=<SHA256_HASH> ``` Where `<SHA256_HASH>` is the SHA256 hash of `owner/repository` 3. **Verification Process:** - When a `.pages` file specifies a custom domain - Plugin performs DNS TXT lookup on the domain - Compares TXT record value with expected hash (using constant-time comparison to prevent timing attacks) - Only registers domain mapping if verification succeeds ### Example For repository `squarecows/bovine-website` with custom domain `bovine.squarecows.com`: 1. **Generate hash:** ```bash ./examples/generate-dns-verification-hash.sh squarecows bovine-website # Output: 73bb8214899661e7f7900c77714586cc51702e6cf26a58c62e17fa9d88f3d3d3 ``` 2. **Add DNS TXT record:** ``` TXT bovine.squarecows.com bovine-pages-verification=73bb8214899661e7f7900c77714586cc51702e6cf26a58c62e17fa9d88f3d3d3 ``` 3. **Add to `.pages` file:** ```yaml enabled: true custom_domain: bovine.squarecows.com ``` 4. **Activate:** Visit `https://squarecows.pages.example.com/bovine-website` to register (DNS verification will be performed automatically) ### Features ✅ **Security:** - SHA256 hashing of repository identifier - Timing attack prevention with `crypto/subtle.ConstantTimeCompare` - Proof of domain ownership required ✅ **Admin Control:** - Opt-in configuration (disabled by default) - No breaking changes for existing deployments ✅ **Usability:** - Helper script to generate verification hashes - Clear error messages in logs - Comprehensive documentation ✅ **Quality:** - Uses only Go standard library (Yaegi compatible) - 8 comprehensive DNS verification tests - All 59 non-Redis tests passing - Full documentation in README ### Files Changed - `pages.go` - Core verification logic - `dns_verification_test.go` - Test suite (new file) - `examples/generate-dns-verification-hash.sh` - Helper script (new file) - `README.md` - Complete documentation - `CHANGELOG.md` - Feature documentation ### Configuration Reference ```yaml http: middlewares: pages-server: plugin: pages-server: pagesDomain: pages.example.com forgejoHost: https://git.example.com # Enable DNS verification for custom domains enableCustomDomainDNSVerification: true ``` ### Documentation Complete setup guide, troubleshooting, and examples available in: - README.md "DNS Verification for Custom Domains" section - Helper script: `examples/generate-dns-verification-hash.sh` ### Branch Feature available on branch: `0.1.0` Will be included in version 0.1.0 release ### Testing To test locally: ```bash git checkout 0.1.0 go test -v -run TestDNS # All DNS verification tests pass ```
ric closed this issue 2025-12-03 23:41:53 +00:00
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
SquareCows/pages-server#10
No description provided.