From 82bfe278bfc0fac32db077eb9acaf49d91632488 Mon Sep 17 00:00:00 2001 From: Catherine Date: Fri, 19 Sep 2025 00:57:54 +0000 Subject: [PATCH] [security] Restrict `X-Pages-Branch` to shared secret authorization only. --- src/auth.go | 23 +++++++++++++++++++++-- src/pages.go | 9 ++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/auth.go b/src/auth.go index 015aa3f..433ac98 100644 --- a/src/auth.go +++ b/src/auth.go @@ -185,7 +185,7 @@ func authorizeRequest(r *http.Request, allowWildcard bool) ([]string, error) { causes := []error{AuthError{http.StatusUnauthorized, "unauthorized"}} if InsecureMode() { - log.Println("auth: INSECURE mode: allow any") + log.Println("auth: INSECURE mode: allow *") return nil, nil // for testing only } @@ -195,7 +195,7 @@ func authorizeRequest(r *http.Request, allowWildcard bool) ([]string, error) { } else if err != nil { // bad request return nil, err } else { - log.Println("auth: DNS challenge: allow any") + log.Println("auth: DNS challenge: allow *") return repoURLs, nil } @@ -254,3 +254,22 @@ func AuthorizeRepository(repoURL string, allowRepoURLs []string) error { } } } + +// The purpose of `allowRepoURLs` is to make sure that only authorized content is deployed +// to the site despite the fact that the non-shared-secret authorization methods allow anyone +// to impersonate the legitimate webhook sender. (If switching to another repository URL would +// be catastrophic, then so would be switching to a different branch.) +func AuthorizeBranch(branch string, allowRepoURLs []string) error { + if allowRepoURLs == nil { + return nil // any + } + + if branch == "pages" { + return nil + } else { + return AuthError{ + http.StatusUnauthorized, + fmt.Sprintf("branch %s: password authorization required", branch), + } + } +} diff --git a/src/pages.go b/src/pages.go index d0eb620..2e96bed 100644 --- a/src/pages.go +++ b/src/pages.go @@ -181,9 +181,12 @@ func putPage(w http.ResponseWriter, r *http.Request) error { return err } - branch := r.Header.Get("X-Pages-Branch") - if branch == "" { - branch = "pages" + branch := "pages" + if customBranch := r.Header.Get("X-Pages-Branch"); customBranch != "" { + branch = customBranch + } + if err := AuthorizeBranch(branch, allowedRepoURLs); err != nil { + return err } ctx, cancel := context.WithTimeout(r.Context(), updateTimeout)