3.9 KiB · text History 67bd0f9

Authentication & Authorization

Implemented Controls

Multi-Factor Authentication

  • TOTP (lib/git_gud/accounts/two_factor.ex, lib/git_gud/accounts/recovery_code.ex)

    • RFC 6238 compliant time-based one-time passwords
    • 10 single-use recovery codes per user (bcrypt-hashed)
    • Instance-level enforcement configurable via TwoFactor.enforcement_status/1
    • Grace period support (TwoFactor.enforced_at vs TwoFactor.grace_period_days)
    • Attempt tracking via TwoFactorAttempts (shared with login)
  • WebAuthn (lib/git_gud/accounts/webauthn.ex, lib/git_gud/accounts/webauthn_credential.ex)

    • Passwordless or second-factor authentication
    • Ceremony managed via Wax library
    • Sudo-mode gating for credential changes
    • Credential management through WebauthnController
  • Magic Links — Email-based authentication via UserNotifier

    • Token-based login without password entry
    • Tokens stored server-side with expiry

Session Management

  • Session tokens stored in users_tokens table

    • 14-day expiry window
    • Server-side revocation capability
    • Renewal on activity (reissue after 7 days)
    • Session fixation prevention via renew_session/2 on login
    • Cross-session invalidation via disconnect_sessions/1
  • Remember-me cookies

    • Signed cookies with 14-day persistence
    • Tied to user’s authenticated_at timestamp

Personal Access Tokens

  • Scoped tokens (lib/git_gud/accounts/personal_access_token.ex)

    • Scope-based access control (e.g., issues:read, repo:write)
    • Stored as hashes (not plaintext)
    • Explicit scope checking in mobile API controller
    • Per-action validation in api/mobile/ controllers
  • Runner JWTs (lib/git_gud/workflows/runner_jwt.ex)

    • Per-job short-lived tokens minted on FetchTask
    • Claims: sub, jti, tid (task ID), rid (run ID), pid (repo ID), perm (permissions)
    • Verified via RunnerJwt.verify_active/1 which checks job is still running
    • 5-minute grace period after job completion (for post-job steps)
    • Permissions scoped to workflow permissions: block

Authorization Layers

  • Repository visibility via RepoAuth plug

    • Read-gate enforced at LiveView mount level
    • Visibility enforcement: public, internal, private
    • Preload-based checks to minimize queries
  • Admin scope via Scope.for_user/1

    • Gated through require_admin mount hook
    • Instance-level admin-only routes
  • Sudo mode

    • Password or second-factor re-authentication required
    • 10-minute validity window for sensitive operations
    • Credential changes gated behind re-authentication

Security Observations

Critical

Insecure default secrets in config (config/config.exs:141-149)

  • Secrets master key default: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" (all zeros)
  • Runner JWT secret default: "dev-runner-jwt-secret-do-not-use-in-prod"
  • If runtime.exs doesn’t override these, all secrets are encrypted with a known key and tokens are forgeable
  • Mitigation: production deployment must override via environment variables

High

HS256-only JWT signing (lib/git_gud/workflows/runner_jwt.ex:174)

  • Runner JWTs use symmetric HS256 signing
  • Same secret signs all tokens across the instance
  • If leaked from any single runner, attacker can mint arbitrary runner tokens
  • No key rotation at JWT layer (only app-level master key rotation for secrets)
  • Recommendation: consider asymmetric signing (RS256/ES256) or at minimum per-instance secret rotation

Medium

No explicit account lockout

  • Only MFA attempts are tracked via TwoFactorAttempts
  • No lockout mechanism for failed login attempts
  • Recommendation: add progressive rate limiting or account lockout after N failed attempts

PAT scopes not uniformly validated

  • Scoped token validation exists in mobile API but not consistently across all REST API endpoints
  • Recommendation: centralize PAT scope validation in a plug applied to all API pipelines