API Security & Rate Limiting
API Endpoints
Personal Access Tokens (PAT)
Scopes (lib/git_gud/accounts/personal_access_token.ex)
- Granular scope system (e.g.,
issues:read,issues:write,repo:read,repo:write) - Stored as hashes — cannot be recovered if lost
- Explicit scope checking in mobile API controllers
Mobile API (lib/git_gud_web/controllers/api/mobile/)
- Auth via
x-api-keyorAuthorization: Bearer <token>header - Per-action scope validation in controller actions
- Endpoints:
AuthController— login, register, token refreshCiController— CI/CD status, job logsIssueController— issues CRUDLabelController— labels CRUDPackageController— package uploads/downloadsPullRequestController— PRs, reviews, commentsRepositoryController— repos, branches, commits, blobsSessionController— session managementWikiController— wiki pages
Gitea-Compatible REST API
lib/git_gud_web/controllers/api/v1/
OrgController— organization managementRepositoryController— repository CRUD, forks, settingsWorkflowController— CI workflow management- Auth: per-endpoint handling (public read, PAT for write, runner token for CI)
Runner Protocol (CI)
lib/git_gud_web/controllers/runner_controller.ex
- Twirp/protobuf endpoints at
/api/actions/_apis/runner.v1.* - Methods:
Ping,Register,Declare,FetchTask,FetchSingleTask,UpdateTask,UpdateLog - Auth:
x-runner-tokenheader orBearertoken - Runner registration uses one-shot token (
Runners.consume_registration_token/1) - Per-job JWTs minted on task claim (
RunnerJwt.mint/3)
Artifact/Cache APIs
ActionsArtifactController—/api/actions/_apis/pipelines/workflows/:run_id/artifacts/*ActionsCacheController—/api/actions/_apis/artifactcache/*WorkflowArtifactController—/api/actions/_apis/workflow-artifacts/*- Auth:
RunnerJwtAuthplug — verifies per-job JWT and job is active
OCI Registry API
lib/git_gud_web/controllers/registry_controller.ex
- Docker registry v2 protocol
- Token-based auth at
/v2/token - JWT tokens for push/pull operations
- Token signing via
GitGud.Packages.Token(RS256/HS256 configurable)
ActivityPub/WebFinger
lib/git_gud_web/controllers/ap_actor_controller.ex
- HTTP signatures (RSA-SHA256) with digest verification
- Clock skew validation: 5-minute window
- Content negotiation for JSON-LD / ActivityPub objects
- WebFinger at
/.well-known/webfinger
lib/git_gud_web/plugs/ap_dispatcher.ex
- Routes ActivityPub requests to inbox handlers
- Validates signature chains for federated actors
Rate Limiting
Implemented Controls
Federation Inbox (lib/git_gud/federation/rate_limiter.ex)
- 60 requests/minute/source host
- Allowlisted hosts: 5x multiplier
- ETS-based counters with 60-second sweep interval
- Prevents inbox flooding from remote instances
MFA Attempts (lib/git_gud/accounts/two_factor_attempts.ex)
- Tracks failed MFA verification attempts
- Shared with login attempt tracking
Missing Rate Limiting
- Login/Register endpoints — No rate limiting on authentication attempts
- Password reset/Magic links — No throttling on email sending
- PAT token verification — No brute-force protection on token endpoint
- API endpoints — No rate limiting on mobile API, REST API, or runner endpoints
- Webhook delivery — No rate limiting on outbound webhook retries
- Runner protocol — No rate limiting on
FetchTaskcalls
Security Observations
High
No rate limiting on authentication endpoints
- Login, registration, and magic link endpoints have no rate limiting
- Vulnerable to credential stuffing and brute-force attacks
- Recommendation: add IP-based rate limiting (e.g., 10 requests/minute for login, 5/hour for magic links)
- Consider CAPTCHA or proof-of-work after N failed attempts
No rate limiting on API endpoints
- Mobile API, REST API, and runner protocol endpoints have no rate limiting
- Can be abused for resource exhaustion or denial of service
- Recommendation: add rate limiting via Plug (e.g.,
Plug.RateLimitor custom implementation) - Start with 100 requests/minute per authenticated user, 10/minute for unauthenticated
Medium
PAT scopes not uniformly validated
- Scoped token validation exists in mobile API but not consistently across all REST API endpoints
- Recommendation: create a centralized plug for PAT scope validation
- Apply to all API pipelines (
:api,:mobile_api,:browser_api)
Runner registration token not expired
lib/git_gud_web/controllers/runner_controller.ex:73— Registration uses one-shot token- No evidence of token expiry enforcement in the controller
- If token is never consumed, it remains valid indefinitely
- Recommendation: add expiry to registration tokens (e.g., 30 minutes)
API key exposure in URLs
- Verify API keys are never logged in query parameters
- Recommendation: add logging middleware that redacts sensitive headers/parameters
- Use
Authorizationheader instead of query parameters for API keys
Webhook delivery no rate limiting
lib/git_gud/webhooks.ex— Outbound delivery has no rate limiting- Malicious or misconfigured webhooks can flood external endpoints
- Recommendation: add delivery rate limiting per webhook (e.g., 10 deliveries/minute)
- Include retry backoff with exponential delay and maximum retry count
Low
OCI registry token TTL
config/config.exs:103— Token TTL is 300 seconds (5 minutes)- Short TTL is good for security but increases token refresh overhead
- Ensure token refresh logic in clients handles 401 responses gracefully
ActivityPub clock skew window
- 5-minute clock skew window for HTTP signatures may be too permissive
- Recommendation: make clock skew configurable (e.g.,
max_skew_seconds: 300) - Default to 30 seconds for high-security deployments