CVE-2026-42560
Description
auth provides authentication via oauth2, direct and email. From versions 1.18.0 to before 1.25.2 and 2.0.0 to before 2.1.2, the Patreon OAuth provider maps every authenticated Patreon account to the same local user.ID, instead of deriving a unique ID from the Patreon account returned by Patreon. In practice, this means all Patreon-authenticated users of an application using this library are collapsed into a single local identity. Any application that trusts token.User.ID as the stable account key can end up mixing or fully merging unrelated Patreon users, which can lead to cross-account access, privilege confusion, and subscription-state leakage. This issue has been patched in versions 1.25.2 and 2.1.2.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/go-pkgz/authGo | >= 1.18.0, < 1.25.2 | 1.25.2 |
github.com/go-pkgz/auth/v2Go | >= 2.0.0, < 2.1.2 | 2.1.2 |
Affected products
1Patches
14 files changed · +40 −6
provider/providers.go+1 −1 modified@@ -254,7 +254,7 @@ func NewPatreon(p Params) Oauth2Handler { uinfoJSON := uinfo{} if err := json.Unmarshal(bdata, &uinfoJSON); err == nil { - userInfo.ID = "patreon_" + token.HashID(sha1.New(), userInfo.ID) + userInfo.ID = "patreon_" + token.HashID(sha1.New(), uinfoJSON.Data.ID) userInfo.Name = uinfoJSON.Data.Attributes.FullName userInfo.Picture = uinfoJSON.Data.Attributes.ImageURL
provider/providers_test.go+19 −2 modified@@ -176,7 +176,7 @@ func TestProviders_NewPatreon(t *testing.T) { }, "id": "0000000" }}`)) - assert.Equal(t, token.User{Name: "Corgi The Dev", ID: "patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709", + assert.Equal(t, token.User{Name: "Corgi The Dev", ID: "patreon_4e079d0555e5a2b460969c789d3ad968a795921f", Picture: "https://c8.patreon.com/2/400/0000000", IP: ""}, user, "got %+v", user) udata = UserData{} @@ -201,14 +201,31 @@ func TestProviders_NewPatreon(t *testing.T) { }}`)) assert.Equal( t, - token.User{Name: "Corgi The Dev", ID: "patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709", + token.User{Name: "Corgi The Dev", ID: "patreon_4e079d0555e5a2b460969c789d3ad968a795921f", Picture: "https://c8.patreon.com/2/400/0000000", IP: "", Attributes: map[string]interface{}{"is_paid_sub": true}}, user, "got %+v", user, ) } +// distinct Patreon accounts must produce distinct local user IDs. +// the previous implementation hashed the uninitialized userInfo.ID, so every +// Patreon user collapsed into the same identity. +func TestProviders_NewPatreon_DistinctIDs(t *testing.T) { + r := NewPatreon(Params{URL: "http://demo.remark42.com", Cid: "cid", Csecret: "cs"}) + + alice := r.mapUser(UserData{}, []byte(`{"data":{"attributes":{"full_name":"Alice"},"id":"1111111"}}`)) + bob := r.mapUser(UserData{}, []byte(`{"data":{"attributes":{"full_name":"Bob"},"id":"9999999"}}`)) + + assert.NotEqual(t, alice.ID, bob.ID, "different Patreon ids must map to different local user IDs") + assert.Equal(t, "patreon_2ea6201a068c5fa0eea5d81a3863321a87f8d533", alice.ID) + assert.Equal(t, "patreon_22067cb54a7b24764186f1e48cb4586772733cd7", bob.ID) + + empty := r.mapUser(UserData{}, []byte(`{"data":{"attributes":{"full_name":"Nobody"},"id":""}}`)) + assert.NotEqual(t, alice.ID, empty.ID, "empty Patreon id must not collide with a real one") +} + func TestProviders_NewMicrosoft(t *testing.T) { t.Run("default tenant", func(t *testing.T) { r := NewMicrosoft(Params{URL: "http://demo.remark42.com", Cid: "cid", Csecret: "cs"})
v2/provider/providers.go+1 −1 modified@@ -254,7 +254,7 @@ func NewPatreon(p Params) Oauth2Handler { uinfoJSON := uinfo{} if err := json.Unmarshal(bdata, &uinfoJSON); err == nil { - userInfo.ID = "patreon_" + token.HashID(sha1.New(), userInfo.ID) + userInfo.ID = "patreon_" + token.HashID(sha1.New(), uinfoJSON.Data.ID) userInfo.Name = uinfoJSON.Data.Attributes.FullName userInfo.Picture = uinfoJSON.Data.Attributes.ImageURL
v2/provider/providers_test.go+19 −2 modified@@ -176,7 +176,7 @@ func TestProviders_NewPatreon(t *testing.T) { }, "id": "0000000" }}`)) - assert.Equal(t, token.User{Name: "Corgi The Dev", ID: "patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709", + assert.Equal(t, token.User{Name: "Corgi The Dev", ID: "patreon_4e079d0555e5a2b460969c789d3ad968a795921f", Picture: "https://c8.patreon.com/2/400/0000000", IP: ""}, user, "got %+v", user) udata = UserData{} @@ -201,14 +201,31 @@ func TestProviders_NewPatreon(t *testing.T) { }}`)) assert.Equal( t, - token.User{Name: "Corgi The Dev", ID: "patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709", + token.User{Name: "Corgi The Dev", ID: "patreon_4e079d0555e5a2b460969c789d3ad968a795921f", Picture: "https://c8.patreon.com/2/400/0000000", IP: "", Attributes: map[string]interface{}{"is_paid_sub": true}}, user, "got %+v", user, ) } +// distinct Patreon accounts must produce distinct local user IDs. +// the previous implementation hashed the uninitialized userInfo.ID, so every +// Patreon user collapsed into the same identity. +func TestProviders_NewPatreon_DistinctIDs(t *testing.T) { + r := NewPatreon(Params{URL: "http://demo.remark42.com", Cid: "cid", Csecret: "cs"}) + + alice := r.mapUser(UserData{}, []byte(`{"data":{"attributes":{"full_name":"Alice"},"id":"1111111"}}`)) + bob := r.mapUser(UserData{}, []byte(`{"data":{"attributes":{"full_name":"Bob"},"id":"9999999"}}`)) + + assert.NotEqual(t, alice.ID, bob.ID, "different Patreon ids must map to different local user IDs") + assert.Equal(t, "patreon_2ea6201a068c5fa0eea5d81a3863321a87f8d533", alice.ID) + assert.Equal(t, "patreon_22067cb54a7b24764186f1e48cb4586772733cd7", bob.ID) + + empty := r.mapUser(UserData{}, []byte(`{"data":{"attributes":{"full_name":"Nobody"},"id":""}}`)) + assert.NotEqual(t, alice.ID, empty.ID, "empty Patreon id must not collide with a real one") +} + func TestProviders_NewMicrosoft(t *testing.T) { t.Run("default tenant", func(t *testing.T) { r := NewMicrosoft(Params{URL: "http://demo.remark42.com", Cid: "cid", Csecret: "cs"})
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-f6qq-3m3h-4g42ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-42560ghsaADVISORY
- github.com/go-pkgz/auth/commit/c0b15ee72a8401da83c01781c16636c521f42698nvdWEB
- github.com/go-pkgz/auth/releases/tag/v1.25.2nvdWEB
- github.com/go-pkgz/auth/releases/tag/v2.1.2nvdWEB
- github.com/go-pkgz/auth/security/advisories/GHSA-f6qq-3m3h-4g42nvdWEB
News mentions
0No linked articles in our index yet.