Skip to content

Security fixes and updates - #131

Merged
lucasdillmann merged 4 commits into
mainfrom
updates-and-other-fixes
Jun 21, 2026
Merged

Security fixes and updates#131
lucasdillmann merged 4 commits into
mainfrom
updates-and-other-fixes

Conversation

@lucasdillmann

Copy link
Copy Markdown
Owner

No description provided.

@lucasdillmann lucasdillmann self-assigned this Jun 21, 2026
@lucasdillmann lucasdillmann changed the title Security fixes and updated Security fixes and updates Jun 21, 2026
@sonarqubecloud

Copy link
Copy Markdown

@lucasdillmann
lucasdillmann marked this pull request as ready for review June 21, 2026 19:27
@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown

Greptile Summary

This 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.

  • Race condition fix: A new FinishOnboarding command is introduced that delegates to TryCreateInitialUser in the database layer. That method wraps the check-then-insert in a database-level exclusive lock (LOCK TABLE ... IN EXCLUSIVE MODE for PostgreSQL; ROLLBACK; BEGIN IMMEDIATE for SQLite), ensuring exactly one winner under concurrent requests. The handler now maps ErrOnboardingAlreadyCompleted to HTTP 403 instead of panicking.
  • Dependency updates: modernc.org/sqlite goes from 1.51.0 to 1.53.0, golang.org/x/crypto to 0.53.0, quic-go to 0.60.0, vite to 8.0.16, and many other minor bumps across all modules.
  • Test coverage: Comprehensive unit tests at every layer (handler, service, repository) are added, including a 10-goroutine concurrency test that verifies exactly one creation succeeds.

Confidence Score: 5/5

Safe 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.

Important Files Changed

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
Loading
%%{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
Loading

Reviews (2): Last reviewed commit: "Fixes, updates and improvements" | Re-trigger Greptile

Comment thread database/user/repository.go
Comment thread database/user/repository.go
@lucasdillmann
lucasdillmann merged commit 0586b4e into main Jun 21, 2026
@lucasdillmann
lucasdillmann deleted the updates-and-other-fixes branch June 21, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant