Commit 367c79588a

367c79588a5dc38a15048727ad83f8e49480e445

parent: 11114e655e

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-29 02:51 UTC

wiki, changelog: import-issues connects only to checked addresses

Closes #301

Layout: unified · split

.gitbay/wiki/Architecture/09-Controls.org +1 −1
@@ -75,7 +75,7 @@ chapter names of OWASP ASVS 4.0 where one fits.
75 75
76| Control | Status | Evidence | 76| Control | Status | Evidence |
77|---------------------------------------------+----------+------------------------------------------------------------------| 77|---------------------------------------------+----------+------------------------------------------------------------------|
78| SSRF protection on user-supplied URLs | partial | webhooks at save and connect; mirrors at save and sync, =repo import= before its fetch, git pinned to the checked address (=internal/gitpin=); =repo import-issues --api-base= checked once and fetched unpinned (#301) | 78| SSRF protection on user-supplied URLs | in place | webhooks at save and connect; mirrors at save and sync, =repo import= and =repo import-issues= before they fetch, git and the import API client pinned to the checked address (=internal/gitpin=) |
79| Webhook payload integrity | in place | HMAC-SHA256 header | 79| Webhook payload integrity | in place | HMAC-SHA256 header |
80| SMTP credentials protected in transit | in place | STARTTLS required for non-local relays, implicit TLS optional (=internal/mail/mail.go=) | 80| SMTP credentials protected in transit | in place | STARTTLS required for non-local relays, implicit TLS optional (=internal/mail/mail.go=) |
81| Upload size limits | in place | per-owner storage quota at push (=internal/sshd/sshd.go=); API body 1 MiB | 81| Upload size limits | in place | per-owner storage quota at push (=internal/sshd/sshd.go=); API body 1 MiB |
.gitbay/wiki/Architecture/10-Known-Gaps.org −1
@@ -13,7 +13,6 @@ what the 2026-09-27 review found; remove a row when its issue closes.
13| #259 | Recovery | No restore has been exercised; the drill is written (Admin wiki) and not yet run | high | 13| #259 | Recovery | No restore has been exercised; the drill is written (Admin wiki) and not yet run | high |
14| #260 | CI network | Builds share the runner's source address; no egress policy | medium | 14| #260 | CI network | Builds share the runner's source address; no egress policy | medium |
15| #261 | Various | Migration foreign-key check after commit; three web writes bypass dispatch; documentation drift | medium | 15| #261 | Various | Migration foreign-key check after commit; three web writes bypass dispatch; documentation drift | medium |
16| #301 | SSRF | =repo import-issues --api-base= checks the address once; fetches unpinned | medium |
17 16
18* Not filed 17* Not filed
19 18
.gitbay/wiki/Threat-Model.org +9 −6
@@ -98,16 +98,19 @@ connection to a user-supplied address, pass the same SSRF guard: the
98scheme must be http/https and, unless =webhooks.allow_local= is set, 98scheme must be http/https and, unless =webhooks.allow_local= is set,
99the resolved address must not be loopback, private, shared 99the resolved address must not be loopback, private, shared
100(100.64.0.0/10), link-local, or multicast. The webhook dialer re-checks 100(100.64.0.0/10), link-local, or multicast. The webhook dialer re-checks
101at connect time, and mirror sync and =repo import= resolve and check 101at connect time, and mirror sync, =repo import= and =repo
102immediately before running git and pin it to the checked addresses 102import-issues= resolve and check immediately before running git and pin
103(=internal/gitpin=), so a DNS answer that changes after validation 103it to the checked addresses (=internal/gitpin=), so a DNS answer that
104still cannot reach private space. Redirects are never followed. 104changes after validation still cannot reach private space;
105=import-issues= holds its API client to the API host's checked
106addresses the same way, with no proxy taken from the environment.
107Redirects are never followed.
105=repo import= refuses =git://=, which cannot be pinned. Mirror sync 108=repo import= refuses =git://=, which cannot be pinned. Mirror sync
106and =repo import= refuse a host written as a bare number or in 109and =repo import= refuse a host written as a bare number or in
107hex/octal (=0x7f.1=, =2130706433=, =127.1=) rather than dotted 110hex/octal (=0x7f.1=, =2130706433=, =127.1=) rather than dotted
108decimal, since that form resolves differently across parsers; =repo 111decimal, since that form resolves differently across parsers; =repo
109mirror add= refuses it when the mirror is saved. GitHub-history import (=repo 112mirror add= refuses it when the mirror is saved, and =repo
110import-issues --api-base=) is not yet pinned (#301). 113import-issues= refuses it in =--api-base=.
111 114
112* Rendering pushed markup 115* Rendering pushed markup
113 116
CHANGELOG.org +7
@@ -19,6 +19,13 @@ anything beyond "replace the binary and restart" is needed.
19 global gitconfig are ignored. A source that redirects (a renamed 19 global gitconfig are ignored. A source that redirects (a renamed
20 repository) fails; import from the URL it redirects to. Needs git 20 repository) fails; import from the URL it redirects to. Needs git
21 2.37 or later on the server (#298). 21 2.37 or later on the server (#298).
22- =repo import-issues= resolves and checks the API host and the git
23 host once and connects only to the checked addresses: the API client
24 dials them with no proxy from the environment and follows no
25 redirect, and the pull-head fetch runs git pinned, with redirects
26 off and without the system and global gitconfig. =--api-base= refuses
27 credentials, a query or a fragment. An API that redirects (a renamed
28 repository) fails; import under the new name (#301).
22- =repo mirror add= refuses a host written numerically (=127.1=, 29- =repo mirror add= refuses a host written numerically (=127.1=,
23 =2130706433=, =0x7f.1=) when the mirror is added, rather than at its 30 =2130706433=, =0x7f.1=) when the mirror is added, rather than at its
24 first sync (#298). 31 first sync (#298).