Commit Graph

51 Commits

Author SHA1 Message Date
Catherine
c5c5306688 [breaking-change] Use a distinct scope for forge DNS allowlist authz.
Before this commit, a `_git-pages-repository.<host>` TXT record would
allow both forge DNS allowlist authorization, as well as normal DNS
allowlist authorization. This means that a site set up to have its
contents updated by a Forgejo Action could have its contents replaced
by the contents of the repository which contains the Forgejo Action,
which will effectively erase the site in most cases. This is a classic
confused deputy scenario.

To fix this, forge DNS allowlist authorization now uses a distinct
`_git-pages-forge-allowlist.<host>` TXT record, removing ambiguity
that allows this scenario to happen.

The issue was introduced in 27a6de792c
and existed in `main` for about a hour, so it is unlikely anybody
has been impacted by this.
2026-04-23 15:20:32 +00:00
Catherine
27a6de792c Allow using forge authorization with non-wildcard domains.
The new authorization method combines DNS allowlist and existing forge
authorization methods: DNS records are used to determine the allowed
repository URL, and forge authorization is used to check for push
permissions to that URL.
2026-04-22 01:59:37 +00:00
Catherine
2c109a5e1e Factor out common authorization code. NFC
This commit unifies most of the implementation of `AuthorizeDeletion`
and `AuthorizeUpdateFromArchive`, with the latter additionally checking
that the repository URL in the authorization grant follows the limits.

This is done in preparation of adding a second forge authorization
sub-mechanism that can handle non-wildcard domains.
2026-04-22 01:59:37 +00:00
Catherine
d17c645927 Improve forge authorization error message for invalid tokens.
Before:

    - not authorized by forge (wildcard)
      - cannot check repository permissions: GET https://codeberg.org/api/v1/repos/whitequark/whitequark.codeberg.page returned 401 Unauthorized

After:

    - not authorized by forge (wildcard)
      - no access to whitequark/whitequark.codeberg.page or invalid token
2026-04-22 01:59:37 +00:00
Catherine
57e9d05c7f Update default index branch name for codeberg-pages-compat quirk.
The actual Codeberg Pages v2 server uses the Forgejo default branch
for the index repository. The quirk previously used the `main` branch
unconditionally.

This is complex to implement, so per discussion with gusted we have
decided to change the default branch to `pages` so that it has parity
with non-Codeberg-specific behavior.
2026-04-22 00:47:49 +00:00
Catherine
5258bf756b Add support for Netlify Basic-Auth: mechanism. 2026-03-29 12:11:56 +00:00
Catherine
559f0c6ae8 Use right URL when fetching Forgejo user data for audit. 2026-03-08 00:16:13 +00:00
miyuko
9e9664013b Record the authorized forge user's name in the audit log. 2026-03-03 03:21:40 +00:00
miyuko
3e377986bc Accept forge authorization for deleting a site. 2026-03-03 01:29:27 +00:00
Catherine
0d33c64372 [breaking-change] Only allow a single [[wildcard]].index-repo.
The git-pages webhook security model depends on there being
a 1:1 mapping between site URLs and repositories; being able to
specify multiple of them breaks this model, as anyone could switch
the published site from one to the other if both repositories exist.
2026-01-19 02:25:01 +00:00
Catherine
c88d04c71b Add a relaxed-idna feature to allow some uses of _ in hostnames.
This is added to aid migration from Codeberg Pages v2. Forgejo allows
both `_` and `-` in usernames, and it is necessary to be able to accept
host names like `user_name.codeberg.page` under a wildcard domain.
(It is not possible to get a TLS certificate for a host name like this,
so only a wildcard certificate will be able to cover it.)
2025-12-12 02:27:22 +00:00
Catherine
62ef4a5366 Make project name validation more consistent and stricter.
Previously, you could issue e.g. a `GET /%2e%2e/%2e%2e` and it would
get interpreted as a parent directory path segment in the handler.
This didn't result in a path traversal vulnerability when passed to
the S3 backend because of a `path.Clean()` call indirectly done by
`makeWebRoot()`, but it's prudent to not take chances.
2025-12-07 20:24:50 +00:00
Catherine
8fa986015d Process IDNA host names. 2025-12-07 19:28:05 +00:00
Catherine
8b049da3c7 Treat allowed-repository-url-prefixes = [] the same as unspecified.
Previously, this would disallow all git clones except for those via
wildcard domains. This is highly unintuitive. It also meant that
disabling this function via environment variable was not possible.
2025-12-07 12:55:41 +00:00
miyuko
cb7802df10 Pass the context to logging functions. 2025-11-22 07:05:07 +00:00
Catherine
b1b8ae26e8 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.
2025-11-21 03:49:38 +00:00
Catherine
eaf77565bc Improve configuration reload and clarify scope.
This commit also moves all of the globals into `main.go`.
2025-11-20 04:06:09 +00:00
Catherine
6db850e2c4 Allow downloading entire site via CLI or HTTP.
The HTTP endpoint is `/.git-pages/archive.tar` and it is gated behind
a feature flag `archive-site`. It serially downloads every blob and
writes it to the client in a chunked response, optionally compressed
with gzip or zstd as per `Accept-Encoding:`. It is authorized the same
as `/.git-pages/manifest.json`, for the same reasons.

The CLI operation is `-get-archive <site-name>` and it writes a tar
archive to stdout. This could be useful for an administrator to review
the contents of a site in response to a report.

Both `_headers` and `_redirects` files are present in the output,
reconstituted from the manifest.
2025-11-20 02:09:49 +00:00
Catherine
0b2db170b8 Allow updating wildcard domain sites from an archive with a forge token. 2025-11-19 04:10:02 +00:00
Catherine
457dd60aa0 Factor out authentication helpers. NFC 2025-11-19 02:53:48 +00:00
Catherine
d604455e1f Ignore trailing . in hostnames.
This means that e.g. `https://site.tld.` will be treated the same as
`https://site.tld`. In DNS, the trailing empty label means "root domain"
and is usually ignored when present. There are some sites with links
that don't work otherwise.
2025-11-15 03:12:03 +00:00
Catherine
b70a9ad4dd Allow only ssh, http, and https schemes for clone URLs. 2025-11-14 23:12:53 +00:00
Catherine
c4b3671a53 Add [[wildcard]].index-repo-branch option (pages by default). 2025-11-05 23:00:32 +00:00
Catherine
d1be93919f Make installable with go install. 2025-10-22 05:24:55 +00:00
miyuko
87262e82f0 Swallow DNS allowlist parsing errors if at least one record is valid. 2025-10-15 02:36:14 +01:00
Catherine
d887ae1602 Allow metadata retrieval with Codeberg Pages v2 authorization method. 2025-10-09 13:48:46 +00:00
Catherine
e0b659f668 Add [limits].allowed-repository-url-prefixes configuration option.
This is useful to limit updates to a specific Git forge.
Naturally, enabling this option disables updates from archive.
2025-10-09 13:48:15 +00:00
Catherine
15107298b2 Allow a trailing dot in Codeberg Pages v2 DNS TXT authentication method. 2025-10-07 19:00:46 +00:00
Catherine
80aa8e2901 Add Codeberg Pages v2 specific DNS authorization mechanism.
Feature-gated behind `codeberg-pages-compat` since it has no generic
use outside of that specific deployment.
2025-09-25 01:18:47 +00:00
Catherine
d26fe98577 Refactor authorization code to handle non-pages branches. NFC 2025-09-24 22:54:58 +00:00
Catherine
b1c372ea54 All subdomains of a forbidden domain are forbidden as well. 2025-09-22 20:00:54 +00:00
Catherine
c11114149c Allow marking a domain as unconditionally forbidden to update. 2025-09-22 19:39:23 +00:00
Catherine
a159dba0b8 [breaking-change] Redesign environment var configuration overrides.
This is done using reflection to avoid boilerplate and potential desync
of the two configuration interfaces. The `[[wildcards]]` section did
not fit well into the "splat every config key" paradigm, so it is
unmarshalled as a whole from a JSON payload in an environment variable.

This commit also splits up the `Config` type into small per-section
struct types and removes most references to the global `config` in
favor of passing pointers to sections around.

A new option, `-print-config-env-vars`, shows the names and types of
all of the available configuration knobs.
2025-09-22 07:02:42 +00:00
Catherine
5765fa7ffa Proxy requests for unknown sites via wildcard fallback URL (if any). 2025-09-21 02:39:44 +00:00
Catherine
d5302e4358 [breaking-change] Allow multiple wildcard domains to be configured. 2025-09-21 00:29:51 +00:00
Catherine
bd294982b2 Disallow Host: values starting with a dot.
Although these should never appear in first place, allowing them
to proceed into application logic may cause conflicts with reserved
manifest names.
2025-09-20 07:41:34 +00:00
Catherine
15b2f1ea39 Allow zip and tar archive uploads PUT request. 2025-09-20 07:16:10 +00:00
Catherine
e92b48b99f Expose site manifest to authorized clients.
As the rules for serving a site get more complex, being able to see
the git-pages' view of the site structure will become increasingly
valuable.

Unauthorized clients are rejected to make enumeration more difficult.
While git-pages isn't designed to serve sensitive data, it is prudent
to recognize that someone somewhere will do it anyway.
2025-09-19 16:58:01 +00:00
Catherine
46d54503ee Fix DNS allowlist not applying to POST requests. 2025-09-19 14:10:26 +00:00
Catherine
9810a346f0 Refactor authorization code. NFC 2025-09-19 04:08:22 +00:00
Catherine
82bfe278bf [security] Restrict X-Pages-Branch to shared secret authorization only. 2025-09-19 00:57:54 +00:00
Catherine
512d5e928a Clearly indicate insecure mode at startup. 2025-09-19 00:36:35 +00:00
Catherine
af5deb60c6 [breaking-change] Accept multiple index repository patterns. 2025-09-18 23:51:20 +00:00
Catherine
3393c077b5 Add DNS allowlist authorization.
Also, improve authorization docs and tighten rules for `INSECURE`.
2025-09-18 21:53:55 +00:00
Catherine
929aedfd2c Use strings.Trim{Prefix,Suffix}. NFC 2025-09-18 20:05:59 +00:00
Catherine
3c46169ba6 Refactor authentication code. 2025-09-18 19:23:59 +00:00
miyuko
cf8abbca28 Wrap errors when calling fmt.Errorf. 2025-09-17 13:14:42 +01:00
Catherine
7fc81d3d97 [breaking-change] Rearchitect for better object store compatibility.
Co-authored-by: bin <flumf@users.noreply.github.com>
2025-09-17 05:59:50 +00:00
Catherine
8b8431201b Allow Authorization: Basic as a fallback for GitHub, etc. 2025-09-16 15:57:55 +00:00
Catherine
abaf6d993b Add support for a wildcard domain. 2025-09-15 08:11:30 +00:00