Security fixes and updates - #131
Conversation
|
Greptile SummaryThis PR fixes a reported security vulnerability (GHSA-pxcx-fv34-x9p5) where a race condition in the onboarding flow could allow multiple admin users to be created simultaneously. It also bumps the Go toolchain to 1.26.4, nginx to 1.31.2-alpine, and refreshes multiple Go and frontend dependencies.
Confidence Score: 5/5Safe to merge — the race condition fix is correct at both the service and database layers, and dependency bumps are routine patch/minor updates. The onboarding race condition is fixed with a proper database-level exclusive lock, the error is mapped to a 403 at the handler layer, and every changed code path is covered by new unit and integration tests. Dependency updates are all patch or minor version bumps with no breaking API changes visible in the diff. No files require special attention.
|
| Filename | Overview |
|---|---|
| core/user/service.go | Adds FinishOnboarding method that validates, hashes the password, then calls TryCreateInitialUser — correctly guarded by validator so Password=nil cannot cause a nil dereference |
| database/user/repository.go | Adds TryCreateInitialUser with per-dialect table locking; lockUserTable handles both PostgreSQL (LOCK TABLE EXCLUSIVE) and SQLite (ROLLBACK; BEGIN IMMEDIATE) correctly |
| api/user/onboarding_finish_handler.go | Handler now calls FinishOnboarding and correctly maps ErrOnboardingAlreadyCompleted to 403; both race paths (pre-check and post-check) are handled |
| database/user/repository_test.go | New concurrent test (10 goroutines) correctly accounts for SQLITE_BUSY by falling through to increment failureCount; assertions hold for both PostgreSQL and SQLite modes |
| core/user/errors.go | New file defining ErrOnboardingAlreadyCompleted sentinel error used to signal the 403 path |
| core/user/commands.go | FinishOnboarding added to Commands interface; mock will be auto-regenerated by the Makefile mock-gen step |
| core/user/repository.go | TryCreateInitialUser added to Repository interface to enforce the atomic check-and-create contract at the database layer |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant C as Client
participant H as OnboardingHandler
participant S as UserService
participant R as UserRepository
participant DB as Database
C->>H: POST /onboarding/finish
H->>S: OnboardingCompleted()
S->>DB: "SELECT COUNT(*)"
DB-->>S: 0
S-->>H: false
H->>S: FinishOnboarding(request)
S->>S: validate + hash password
S->>R: TryCreateInitialUser(user)
R->>DB: BEGIN
R->>DB: LOCK TABLE user exclusive
R->>DB: SELECT EXISTS
DB-->>R: false
R->>DB: INSERT user
R->>DB: COMMIT
R-->>S: true, nil
S-->>H: nil
H->>S: Authenticate(username, password)
S-->>H: SUCCESS + user
H-->>C: 200 OK + JWT
note over C,DB: Concurrent request races same endpoint
C->>H: POST /onboarding/finish
H->>S: FinishOnboarding(request)
S->>R: TryCreateInitialUser(user)
R->>DB: LOCK TABLE or BEGIN IMMEDIATE
DB-->>R: busy or table not empty
R-->>S: false, nil
S-->>H: ErrOnboardingAlreadyCompleted
H-->>C: 403 Forbidden
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant C as Client
participant H as OnboardingHandler
participant S as UserService
participant R as UserRepository
participant DB as Database
C->>H: POST /onboarding/finish
H->>S: OnboardingCompleted()
S->>DB: "SELECT COUNT(*)"
DB-->>S: 0
S-->>H: false
H->>S: FinishOnboarding(request)
S->>S: validate + hash password
S->>R: TryCreateInitialUser(user)
R->>DB: BEGIN
R->>DB: LOCK TABLE user exclusive
R->>DB: SELECT EXISTS
DB-->>R: false
R->>DB: INSERT user
R->>DB: COMMIT
R-->>S: true, nil
S-->>H: nil
H->>S: Authenticate(username, password)
S-->>H: SUCCESS + user
H-->>C: 200 OK + JWT
note over C,DB: Concurrent request races same endpoint
C->>H: POST /onboarding/finish
H->>S: FinishOnboarding(request)
S->>R: TryCreateInitialUser(user)
R->>DB: LOCK TABLE or BEGIN IMMEDIATE
DB-->>R: busy or table not empty
R-->>S: false, nil
S-->>H: ErrOnboardingAlreadyCompleted
H-->>C: 403 Forbidden
Reviews (2): Last reviewed commit: "Fixes, updates and improvements" | Re-trigger Greptile



No description provided.