SSH control commands have no write rate limit; the JSON API has one #148

closed cmc opened this on 2026-09-04 19:27 UTC · security · milestone security

Discussion

cmc 2026-09-04 19:27 UTC

internal/sshd/ratelimit.go throttles authentication failures only, and says so: "successful auths clear the IP's slate". Once a key authenticates, nothing bounds how many control commands it runs.

The JSON API, fronting the same command registry, is limited to 120 requests a minute with writes at a tenth of that (internal/httpd/apilimit.go). So the same issue create is rate-limited through one surface and unlimited through the other, and the unlimited one is the primary interface.

Quotas exist for what accumulates — max_repos_per_user, max_bytes_per_user — but not for rate. Nothing caps issues, comments, merge requests, or reviews per account per minute.

This is only a nuisance on an invite-only instance. With registration = "open", which gitbay.org runs, one account can fill a repository's issue tracker as fast as it can open SSH connections, and every one of those writes also enqueues notification mail and webhook deliveries.

Remedy: a per-account write limiter in the dispatcher, so it covers SSH and the API from one place rather than each surface deciding — which is the same argument the command registry itself rests on. The API's existing limiter then becomes a per-IP layer in front of it rather than the only defence.

Worth deciding at the same time: whether an unverified (pending) account should be able to write at all. It currently reaches email verify, email add, whoami and help only, so this is probably already handled — confirm rather than assume.

closed by commit 7f2fd45218 by cmc: control, config, wiki: bound writes per account in the dispatcher

2026-09-06 18:10 UTC