fix(auth,db): avoid OIDC login panic and Close on uninitialized store - #4067
Open
cursor[bot] wants to merge 1 commit into
Open
cursor[bot] wants to merge 1 commit into
cursor[bot] wants to merge 1 commit into
Conversation
OIDC: When a provider returns no id_token and the UserInfo endpoint errors, oidcRedirect accessed userInfo.Profile before checking err, panicking on a nil pointer and crashing the server process. DB: SqlDbConnection.Close() checked d.sql.Db but not d.sql itself, so defer store.Close() after a failed Connect() still panicked (e.g. semaphore setup when the DB connection fails before gorp is initialized). Co-authored-by: Denis Gukov <fiftin@outlook.com>
Author
There was a problem hiding this comment.
Security review
Outcome: No medium, high, or critical vulnerabilities identified in this PR.
Scope reviewed:
api/login.go—oidcClaimsFromUserInforefactor that returns early on UserInfo fetch errors instead of dereferencing a niluserInfopointer.db/sql/SqlDb.go— nil guard inSqlDbConnection.Close()when the store was never connected.
Assessment:
- The OIDC change is a behavioral-preserving panic fix on the UserInfo error path. Successful-login claim extraction (email,
sub,emailVerified, username/name assignment) matches the prior logic; failed UserInfo responses now surface as HTTP 502 instead of crashing the handler. - Attacker-controlled OIDC inputs still pass through existing controls: OAuth state/CSRF validation, authorization-code exchange, ID-token verification (when present), and
resolveExternalUseridentity/email-matching gates. - The database
Close()guard only prevents a nil-pointer panic on shutdown/cleanup; it does not weaken authz or expose data.
No prior automation review threads required resolution.
Sent by Cursor Automation: Find vulnerabilities
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes two crash-on-error-path bugs in the Semaphore server: one in the OIDC login flow when UserInfo retrieval fails, and one in the SQL DB store shutdown path when a connection was never initialized.
Changes:
- Refactors OIDC claim construction into
oidcClaimsFromUserInfo()to avoid nil dereference after a UserInfo error, and wiresoidcRedirectto use it. - Hardens
SqlDbConnection.Close()to no-op safely when the gorpDbMapwas never initialized. - Adds targeted unit tests covering both failure-path regressions.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| db/sql/SqlDb.go | Adds a nil guard in Close() to prevent panics on partially initialized connections. |
| db/sql/SqlDb_test.go | Adds tests ensuring Close() does not panic when never connected. |
| api/login.go | Introduces oidcClaimsFromUserInfo() and updates oidcRedirect to use it, preventing OIDC login panics. |
| api/login_test.go | Adds tests validating claim-building behavior when UserInfo fails and when it contains email/profile fields. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Fixes two server-crash bugs found during daily critical-bug inspection.
Bug 1: OIDC UserInfo nil dereference
Impact: Server process panic during OIDC login when the provider returns no
id_tokenand the UserInfo endpoint errors.Root cause: In
oidcRedirect, claim-building code accesseduserInfo.Profileoutside theif err == nilblock, so a failed UserInfo fetch leftuserInfonil and triggered a nil pointer dereference.Fix: Extract
oidcClaimsFromUserInfo()that returns early on UserInfo error before touchinguserInfo.Trigger scenario: Configure an OIDC provider that does not include
id_tokenin the token response and whose UserInfo endpoint is unreachable or returns an error. Any login attempt crashes the Semaphore server.Bug 2: SqlDb Close on uninitialized connection
Impact: Panic on shutdown when database connection was never fully initialized.
Root cause:
SqlDbConnection.Close()guardedd.sql.Db == nilbut notd.sql == nil. IfConnect()panics before gorp is initialized,defer store.Close()(e.g. insemaphore setup) still dereferences a nild.sql.Fix: Guard with
d.sql == nil || d.sql.Db == nil.Trigger scenario: Run
semaphore setupwith an invalid DB config; connection fails before gorp init, deferredClose()panics.Validation
go test ./api -run TestOidcClaimsFromUserInfo -count=1— passgo test ./db/sql -run 'TestSqlDb.*CloseWithoutConnect' -count=1— passNotes
Recent commits since last inspection (
cd314c1d,742e8761) are CI/GPG-only with no behavioral risk. Workflow migration data-loss issue (2.19.11 per-node inventory/env overrides) remains open on develop.Note
Medium Risk
Touches authentication claim handling and DB lifecycle on failure paths; changes are narrow guards/refactors with tests, but login and shutdown are sensitive.
Overview
Fixes two server panic paths: OIDC login when there is no
id_tokenand UserInfo fails, and database shutdown when the store was never connected.For OIDC, claim building when relying on UserInfo is moved into
oidcClaimsFromUserInfo, which returns the UserInfo error before readinguserInfo(the old flow still toucheduserInfo.Profileafter a failed fetch).oidcRedirectnow calls that helper instead of inlined logic.For the DB layer,
SqlDbConnection.Closenow no-ops whend.sqlis nil as well as whenDbis nil, so deferredClose()after a failedConnect()(e.g. setup with bad config) does not crash.Tests cover UserInfo error/success claim paths and closing without connect.
Reviewed by Cursor Bugbot for commit 73186e3. Bugbot is set up for automated code reviews on this repo. Configure here.