git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge commit from fork

Signed-off-by: Jan Larwig <jan@larwig.com>

commitcc0e0335ea9e33c0220c7ce1181e5d41dcac7b48 authorJan Larwig <jan@larwig.com> dateMon 13 Apr 2026, 18:24 (6 months ago) parentaff369d
4 files changed+44−1
CHANGELOG.md+1 oauthproxy_test.go+18 validator.go+4−1 validator_test.go+21
CHANGELOG.md+1
@@ -13,6 +13,7 @@
1313- [GHSA-f24x-5g9q-753f](https://github.com/oauth2-proxy/oauth2-proxy/security/advisories/GHSA-f24x-5g9q-753f) fix: clear session cookie at beginning of signinpage handler (@fnoehWM / @bella-WI / @tuunit)
1414- [GHSA-5hvv-m4w4-gf6v](https://github.com/oauth2-proxy/oauth2-proxy/security/advisories/GHSA-5hvv-m4w4-gf6v) fix: health check user-agent authentication bypass (@tuunit)
1515- [GHSA-7x63-xv5r-3p2x](https://github.com/oauth2-proxy/oauth2-proxy/security/advisories/GHSA-7x63-xv5r-3p2x) fix: authentication bypass via X-Forwarded-Uri header spoofing (@tuunit)
16+- [GHSA-c5c4-8r6x-56w3](https://github.com/oauth2-proxy/oauth2-proxy/security/advisories/GHSA-c5c4-8r6x-56w3) fix: email validation bypass via malformed multi-@ email claims (@tuunit)
1617
1718# V7.15.1
1819
oauthproxy_test.go+18
@@ -3486,6 +3486,24 @@ func TestAuthOnlyAllowedEmailDomains(t *testing.T) {
34863486 querystring: "?allowed_email_domains=a.b.c.example.com,*.c.example.com",
34873487 expectedStatusCode: http.StatusAccepted,
34883488 },
3489+ {
3490+ name: "UserWithMultipleAtSignsExactDomain",
3491+ email: "attacker@evil.com@example.com",
3492+ querystring: "?allowed_email_domains=example.com",
3493+ expectedStatusCode: http.StatusForbidden,
3494+ },
3495+ {
3496+ name: "UserWithMultipleAtSignsWildcardDomain",
3497+ email: "attacker@evil.com@foo.example.com",
3498+ querystring: "?allowed_email_domains=*.example.com",
3499+ expectedStatusCode: http.StatusForbidden,
3500+ },
3501+ {
3502+ name: "UserWithMultipleAtSignsDotPrefixedDomain",
3503+ email: "attacker@evil.com@foo.example.com",
3504+ querystring: "?allowed_email_domains=.example.com",
3505+ expectedStatusCode: http.StatusForbidden,
3506+ },
34893507 }
34903508
34913509 for _, tc := range testCases {
validator.go+4−1
@@ -110,6 +110,10 @@ func NewValidator(domains []string, usersFile string) func(string) bool {
110110
111111// isEmailValidWithDomains checks if the authenticated email is validated against the provided domain
112112func isEmailValidWithDomains(email string, allowedDomains []string) bool {
113+ if strings.Count(email, "@") != 1 {
114+ return false
115+ }
116+
113117 for _, domain := range allowedDomains {
114118 // allow if the domain is perfect suffix match with the email
115119 if strings.HasSuffix(email, "@"+domain) {
@@ -119,7 +123,6 @@ func isEmailValidWithDomains(email string, allowedDomains []string) bool {
119123 // allow if the domain is prefixed with . or *. and
120124 // the last element (split on @) has the suffix as the domain
121125 atoms := strings.Split(email, "@")
122−
123126 if (strings.HasPrefix(domain, ".") && strings.HasSuffix(atoms[len(atoms)-1], domain)) ||
124127 (strings.HasPrefix(domain, "*.") && strings.HasSuffix(atoms[len(atoms)-1], domain[1:])) {
125128 return true
validator_test.go+21
@@ -404,6 +404,27 @@ func TestValidatorCases(t *testing.T) {
404404 allowedDomains: []string{"*.company.com"},
405405 expectedAuthZ: false,
406406 },
407+ {
408+ name: "CheckThatTwoAtSignsIsInvalid",
409+ email: "attacker@evil.com@company.com",
410+ allowedEmails: []string(nil),
411+ allowedDomains: []string{"company.com"},
412+ expectedAuthZ: false,
413+ },
414+ {
415+ name: "CheckThatTwoAtSignsIsInvalidEvenWithDotPrefix",
416+ email: "attacker@evil.com@company.com",
417+ allowedEmails: []string(nil),
418+ allowedDomains: []string{".company.com"},
419+ expectedAuthZ: false,
420+ },
421+ {
422+ name: "CheckThatTwoAtSignsIsInvalidEvenWithWildcardPrefix",
423+ email: "attacker@evil.com@foo.company.com",
424+ allowedEmails: []string(nil),
425+ allowedDomains: []string{"*.company.com"},
426+ expectedAuthZ: false,
427+ },
407428 }
408429
409430 for _, tc := range testCases {