wiki: Architecture fixes; review gaps filed as #273-#282 !476

merged merged by cmc on 2026-09-28 04:36 UTC · krz/gitbay:docs-arch-links into main

11 files changed, +34 −41

Layout: unified · split

.gitbay/wiki/Architecture/00-Overview.org +6 −6
@@ -38,13 +38,13 @@ the =ReadOnly= count from the =ReadOnly: true= literals in
3838
3939| # | Document | Diagram |
4040|---+----------------------------------------------------+-------------------------------------------------|
41| 1 | [[file:01-System-Context.org][System context]] | [[file:diagrams/01-context.svg][01-context.svg]] |
42| 2 | [[file:02-Components.org][Components]] | [[file:diagrams/02-components.svg][02-components.svg]] |
43| 3 | [[file:03-Deployment.org][Deployment and network]] | [[file:diagrams/03-deployment.svg][03-deployment.svg]] |
44| 4 | [[file:04-Trust-Boundaries.org][Trust boundaries and data flows]] | [[file:diagrams/04-trust-boundaries.svg][04-trust-boundaries.svg]], [[file:diagrams/06-push-flow.svg][06-push-flow.svg]] |
45| 5 | [[file:05-Identity-and-Access.org][Identity and access]] | [[file:diagrams/05-authorization.svg][05-authorization.svg]] |
41| 1 | [[file:01-System-Context.org][System context]] | =01-context.svg= |
42| 2 | [[file:02-Components.org][Components]] | =02-components.svg= |
43| 3 | [[file:03-Deployment.org][Deployment and network]] | =03-deployment.svg= |
44| 4 | [[file:04-Trust-Boundaries.org][Trust boundaries and data flows]] | =04-trust-boundaries.svg=, =06-push-flow.svg= |
45| 5 | [[file:05-Identity-and-Access.org][Identity and access]] | =05-authorization.svg= |
4646| 6 | [[file:06-Data-and-Cryptography.org][Data and cryptography]] | |
47| 7 | [[file:07-CI-and-Supply-Chain.org][CI and supply chain]] | [[file:diagrams/07-ci-flow.svg][07-ci-flow.svg]] |
47| 7 | [[file:07-CI-and-Supply-Chain.org][CI and supply chain]] | =07-ci-flow.svg= |
4848| 8 | [[file:08-Operations.org][Operations]] | |
4949| 9 | [[file:09-Controls.org][Controls matrix]] | |
5050| 10 | [[file:10-Known-Gaps.org][Known gaps]] | |
.gitbay/wiki/Architecture/01-System-Context.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 1. System context
1#+title: System context
22
33[[file:diagrams/01-context.svg]]
44
.gitbay/wiki/Architecture/02-Components.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 2. Components
1#+title: Components
22
33[[file:diagrams/02-components.svg]]
44
.gitbay/wiki/Architecture/03-Deployment.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 3. Deployment and network
1#+title: Deployment and network
22
33[[file:diagrams/03-deployment.svg]]
44
.gitbay/wiki/Architecture/04-Trust-Boundaries.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 4. Trust boundaries and data flows
1#+title: Trust boundaries and data flows
22
33[[file:diagrams/04-trust-boundaries.svg]]
44
.gitbay/wiki/Architecture/05-Identity-and-Access.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 5. Identity and access
1#+title: Identity and access
22
33[[file:diagrams/05-authorization.svg]]
44
.gitbay/wiki/Architecture/06-Data-and-Cryptography.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 6. Data and cryptography
1#+title: Data and cryptography
22
33* Data inventory
44
.gitbay/wiki/Architecture/07-CI-and-Supply-Chain.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 7. CI and supply chain
1#+title: CI and supply chain
22
33[[file:diagrams/07-ci-flow.svg]]
44
.gitbay/wiki/Architecture/08-Operations.org +1 −1
@@ -1,4 +1,4 @@
1#+title: 8. Operations
1#+title: Operations
22
33* Logging
44
.gitbay/wiki/Architecture/09-Controls.org +9 −9
@@ -1,4 +1,4 @@
1#+title: 9. Controls matrix
1#+title: Controls matrix
22
33One row per control an auditor typically asks about. *Status*: =in
44place= (implemented and cited), =partial= (implemented with a stated
@@ -23,8 +23,8 @@ chapter names of OWASP ASVS 4.0 where one fits.
2323| Brute-force limit on SSH auth | in place | 10 failures a minute per IP (=internal/sshd/ratelimit.go=) |
2424| Account enumeration resistance at login | in place | uniform response (=internal/control/loginlink.go=) |
2525| Session cookie flags | in place | HttpOnly, SameSite=Lax, Secure with TLS (=internal/httpd/accounts.go=) |
26| Session lifetime | partial | 7 days absolute, no idle timeout |
27| Credential expiry | partial | API tokens optional; SSH and deploy keys none |
26| Session lifetime | partial | 7 days absolute, no idle timeout (#276) |
27| Credential expiry | partial | API tokens optional; SSH and deploy keys none (#277) |
2828| Revocation takes effect immediately | gap | removed SSH key keeps open connections (#256) |
2929| Delegation bounded by the delegating credential | gap | expiring tokens can mint lasting credentials (#257) |
3030
@@ -56,9 +56,9 @@ chapter names of OWASP ASVS 4.0 where one fits.
5656| Control | Status | Evidence |
5757|---------------------------------------------+----------+------------------------------------------------------------------|
5858| TLS for all authenticated HTTP | in place | ACME or certificate files; HSTS |
59| Secrets encrypted at rest | gap | CI secrets, webhook secrets, mirror tokens stored in clear ([[file:06-Data-and-Cryptography.org][6]]) |
59| Secrets encrypted at rest | gap | CI secrets, webhook secrets, mirror tokens stored in clear (#273) |
6060| Secrets kept out of argv, logs and output | in place | =ReadsStdin=, pruned audit argv, write-only secret commands |
61| Local backups encrypted | gap | tar.gz in clear; offsite copy encrypted by restic |
61| Local backups encrypted | gap | tar.gz in clear; offsite copy encrypted by restic (#274) |
6262| Data retention configurable | in place | =[retention]= (=internal/config/config.go=) |
6363| User data export | in place | =account export= |
6464
@@ -68,16 +68,16 @@ chapter names of OWASP ASVS 4.0 where one fits.
6868|---------------------------------------------+----------+------------------------------------------------------------------|
6969| Security-relevant writes audited | in place | every successful mutating command (=control.go=) |
7070| Authentication failures audited | in place | =auth.failed=, =auth.throttled= |
71| Denied attempts audited | gap | refused commands are not recorded |
72| Audit log tamper resistance | gap | same database, writable by the daemon user |
71| Denied attempts audited | gap | refused commands are not recorded (#275) |
72| Audit log tamper resistance | gap | same database, writable by the daemon user (#275) |
7373
7474** Communications and integrations (V9, V10, V12)
7575
7676| Control | Status | Evidence |
7777|---------------------------------------------+----------+------------------------------------------------------------------|
78| SSRF protection on user-supplied URLs | partial | webhooks at save and connect; mirrors at save only |
78| SSRF protection on user-supplied URLs | partial | webhooks at save and connect; mirrors at save only (#279) |
7979| Webhook payload integrity | in place | HMAC-SHA256 header |
80| SMTP credentials protected in transit | partial | STARTTLS opportunistic; Go refuses PLAIN auth without TLS to a remote host |
80| SMTP credentials protected in transit | partial | STARTTLS opportunistic (#280); Go refuses PLAIN auth without TLS to a remote host |
8181| Upload size limits | in place | per-owner storage quota at push (=internal/sshd/sshd.go=); API body 1 MiB |
8282
8383** CI and build isolation
.gitbay/wiki/Architecture/10-Known-Gaps.org +11 −18
@@ -1,4 +1,4 @@
1#+title: 10. Known gaps
1#+title: Known gaps
22
33Open weaknesses. Issues on krz/gitbay are public; this page gives the
44title and the consequence, not a reproduction. The current list is the
@@ -18,29 +18,22 @@ what the 2026-09-27 review found; remove a row when its issue closes.
1818| #260 | CI network | Builds share the runner's source address; no egress policy | medium |
1919| #261 | Various | Migration foreign-key check after commit; three web writes bypass dispatch; documentation drift | medium |
2020| #262 | Availability | No limit on concurrent git pack generation | high |
21| #273 | Data at rest | CI secrets, webhook secrets and mirror tokens are stored in clear in SQLite | high |
22| #274 | Backups | The local backup archive is not encrypted | medium |
23| #275 | Audit | Refused writes are not audited; the audit table is writable by the daemon user | medium |
24| #276 | Sessions | Web sessions last 7 days with no idle timeout | low |
25| #277 | Credentials | SSH and deploy keys never expire | low |
26| #278 | Login links | =web login= over SSH skips the login-link rate limit | low |
27| #279 | SSRF | Mirror URLs are checked when saved, not when git connects | medium |
28| #280 | Mail | STARTTLS only when the relay offers it | medium |
29| #281 | TLS | No explicit minimum TLS version | low |
30| #282 | Hook socket | Anything that can open =hook.sock= can act as any user | medium |
2131
2232Decisions already taken on these: #256 closes a removed key's
2333connections, running commands included; #257 refuses credential
2434creation from expiring tokens, records which token created each
2535credential, and makes =read= the default scope.
2636
27* Not yet filed
28
29Found during the 2026-09-27 review.
30
31| Area | Gap | Where |
32|------------------+---------------------------------------------------------------------------------------+---------------------------------------------|
33| Data at rest | CI secrets, webhook secrets and mirror tokens are stored in clear in SQLite | =build_secrets=, =webhooks=, =mirrors= |
34| Backups | The local backup archive is not encrypted | =cmd/gitbayd/backup.go= |
35| Audit | Refused commands are not audited; the audit table is writable by the daemon user | =internal/control/control.go= |
36| Sessions | Web sessions have a 7-day absolute lifetime and no idle timeout | =internal/httpd/accounts.go= |
37| Credentials | SSH and deploy keys never expire | =ssh_keys= |
38| Login links | =web login= over SSH is not counted against the 5-per-hour login-link limit | =internal/control/web.go= |
39| SSRF | Mirror URLs are checked when saved but not when git connects, so a DNS change can redirect a mirror to a private address | =internal/control/mirrorcmd.go= |
40| Mail | STARTTLS is used only when the relay offers it | =internal/mail/mail.go= |
41| TLS | Go defaults; no explicit minimum version | =cmd/gitbayd/main.go= |
42| Hook socket | Any process that can open =hook.sock= can claim any user id; it relies on the data directory's permissions | =internal/hookd/hookd.go= |
43
4437* Questions an auditor will ask that have no answer yet
4538
4639| Question | Status |