Restrict DNS Allowlist authorization to index site only.

Otherwise, an undesired degree of freedom permits a third party to
deny access to index site URLs by publishing projects with the same
name.

In the future, the _git-pages-repository TXT record format may be
extended to allow non-index sites to be specified without introducing
undesired degrees of freedom.
This commit is contained in:
Catherine
2025-11-21 03:42:39 +00:00
parent eac02e5758
commit b1b8ae26e8
2 changed files with 11 additions and 1 deletions

View File

@@ -91,7 +91,7 @@ The authorization flow for content updates (`PUT`, `DELETE`, `POST` requests) pr
2. **DNS Challenge:** If the method is `PUT`, `DELETE`, `POST`, and a well-formed `Authorization:` header is provided containing a `<token>`, and a TXT record lookup at `_git-pages-challenge.<host>` returns a record whose concatenated value equals `SHA256("<host> <token>")`, the request is authorized.
- **`Pages` scheme:** Request includes an `Authorization: Pages <token>` header.
- **`Basic` scheme:** Request includes an `Authorization: Basic <basic>` header, where `<basic>` is equal to `Base64("Pages:<token>")`. (Useful for non-Forgejo forges.)
3. **DNS Allowlist:** If the method is `PUT` or `POST`, and a TXT record lookup at `_git-pages-repository.<host>` returns a set of well-formed absolute URLs, and (for `PUT` requests) the body contains a repository URL, and the requested clone URLs is contained in this set of URLs, the request is authorized.
3. **DNS Allowlist:** If the method is `PUT` or `POST`, and the request URL is `scheme://<user>.<host>/`, and a TXT record lookup at `_git-pages-repository.<host>` returns a set of well-formed absolute URLs, and (for `PUT` requests) the body contains a repository URL, and the requested clone URLs is contained in this set of URLs, the request is authorized.
4. **Wildcard Match (content):** If the method is `POST`, and a `[[wildcard]]` configuration section exists where the suffix of a hostname (compared label-wise) is equal to `[[wildcard]].domain`, and (for `PUT` requests) the body contains a repository URL, and the requested clone URL is a *matching* clone URL, the request is authorized.
- **Index repository:** If the request URL is `scheme://<user>.<host>/`, a *matching* clone URL is computed by templating `[[wildcard]].clone-url` with `<user>` and `<project>`, where `<project>` is computed by templating each element of `[[wildcard]].index-repos` with `<user>`, and `[[wildcard]]` is the section where the match occurred.
- **Project repository:** If the request URL is `scheme://<user>.<host>/<project>/`, a *matching* clone URL is computed by templating `[[wildcard]].clone-url` with `<user>` and `<project>`, and `[[wildcard]]` is the section where the match occurred.

View File

@@ -159,6 +159,11 @@ func authorizeDNSAllowlist(r *http.Request) (*Authorization, error) {
return nil, err
}
projectName, err := GetProjectName(r)
if err != nil {
return nil, err
}
allowlistHostname := fmt.Sprintf("_git-pages-repository.%s", host)
records, err := net.LookupTXT(allowlistHostname)
if err != nil {
@@ -166,6 +171,11 @@ func authorizeDNSAllowlist(r *http.Request) (*Authorization, error) {
fmt.Sprintf("failed to look up DNS repository allowlist: %s TXT", allowlistHostname)}
}
if projectName != ".index" {
return nil, AuthError{http.StatusUnauthorized,
"DNS repository allowlist only authorizes index site"}
}
var (
repoURLs []string
errs []error