mirror of
https://github.com/goauthentik/authentik.git
synced 2026-06-17 19:09:11 +03:00
internal: Automated internal backport: CVE-2026-40166.sec.patch to authentik-main (#22299)
* Automated internal backport of patch CVE-2026-40166.sec.patch to authentik-main * gen Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com> Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
committed by
GitHub
parent
f4e868210d
commit
5053167a05
@@ -9,10 +9,10 @@ from rest_framework.fields import CharField, ListField, SerializerMethodField
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
from authentik.core.api.providers import ProviderSerializer
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.users import UserSerializer
|
||||
from authentik.core.api.utils import MetaNameSerializer, ModelSerializer
|
||||
from authentik.providers.oauth2.api.providers import OAuth2ProviderSerializer
|
||||
from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class ExpiringBaseGrantModelSerializer(ModelSerializer, MetaNameSerializer):
|
||||
"""Serializer for BaseGrantModel and ExpiringBaseGrant"""
|
||||
|
||||
user = UserSerializer()
|
||||
provider = OAuth2ProviderSerializer()
|
||||
provider = ProviderSerializer()
|
||||
scope = ListField(child=CharField())
|
||||
|
||||
class Meta:
|
||||
|
||||
+6
-6
@@ -12,8 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import type { OAuth2Provider } from "./OAuth2Provider";
|
||||
import { OAuth2ProviderFromJSON, OAuth2ProviderToJSON } from "./OAuth2Provider";
|
||||
import type { Provider } from "./Provider";
|
||||
import { ProviderFromJSON, ProviderToJSON } from "./Provider";
|
||||
import type { User } from "./User";
|
||||
import { UserFromJSON, UserToJSON } from "./User";
|
||||
|
||||
@@ -31,10 +31,10 @@ export interface ExpiringBaseGrantModel {
|
||||
readonly pk: number;
|
||||
/**
|
||||
*
|
||||
* @type {OAuth2Provider}
|
||||
* @type {Provider}
|
||||
* @memberof ExpiringBaseGrantModel
|
||||
*/
|
||||
provider: OAuth2Provider;
|
||||
provider: Provider;
|
||||
/**
|
||||
*
|
||||
* @type {User}
|
||||
@@ -86,7 +86,7 @@ export function ExpiringBaseGrantModelFromJSONTyped(
|
||||
}
|
||||
return {
|
||||
pk: json["pk"],
|
||||
provider: OAuth2ProviderFromJSON(json["provider"]),
|
||||
provider: ProviderFromJSON(json["provider"]),
|
||||
user: UserFromJSON(json["user"]),
|
||||
isExpired: json["is_expired"],
|
||||
expires: json["expires"] == null ? undefined : new Date(json["expires"]),
|
||||
@@ -107,7 +107,7 @@ export function ExpiringBaseGrantModelToJSONTyped(
|
||||
}
|
||||
|
||||
return {
|
||||
provider: OAuth2ProviderToJSON(value["provider"]),
|
||||
provider: ProviderToJSON(value["provider"]),
|
||||
user: UserToJSON(value["user"]),
|
||||
expires: value["expires"] == null ? value["expires"] : value["expires"].toISOString(),
|
||||
scope: value["scope"],
|
||||
|
||||
+6
-6
@@ -12,8 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import type { OAuth2Provider } from "./OAuth2Provider";
|
||||
import { OAuth2ProviderFromJSON, OAuth2ProviderToJSON } from "./OAuth2Provider";
|
||||
import type { Provider } from "./Provider";
|
||||
import { ProviderFromJSON, ProviderToJSON } from "./Provider";
|
||||
import type { User } from "./User";
|
||||
import { UserFromJSON, UserToJSON } from "./User";
|
||||
|
||||
@@ -31,10 +31,10 @@ export interface TokenModel {
|
||||
readonly pk: number;
|
||||
/**
|
||||
*
|
||||
* @type {OAuth2Provider}
|
||||
* @type {Provider}
|
||||
* @memberof TokenModel
|
||||
*/
|
||||
provider: OAuth2Provider;
|
||||
provider: Provider;
|
||||
/**
|
||||
*
|
||||
* @type {User}
|
||||
@@ -96,7 +96,7 @@ export function TokenModelFromJSONTyped(json: any, ignoreDiscriminator: boolean)
|
||||
}
|
||||
return {
|
||||
pk: json["pk"],
|
||||
provider: OAuth2ProviderFromJSON(json["provider"]),
|
||||
provider: ProviderFromJSON(json["provider"]),
|
||||
user: UserFromJSON(json["user"]),
|
||||
isExpired: json["is_expired"],
|
||||
expires: json["expires"] == null ? undefined : new Date(json["expires"]),
|
||||
@@ -119,7 +119,7 @@ export function TokenModelToJSONTyped(
|
||||
}
|
||||
|
||||
return {
|
||||
provider: OAuth2ProviderToJSON(value["provider"]),
|
||||
provider: ProviderToJSON(value["provider"]),
|
||||
user: UserToJSON(value["user"]),
|
||||
expires: value["expires"] == null ? value["expires"] : value["expires"].toISOString(),
|
||||
scope: value["scope"],
|
||||
|
||||
+2
-2
@@ -39086,7 +39086,7 @@ components:
|
||||
readOnly: true
|
||||
title: ID
|
||||
provider:
|
||||
$ref: '#/components/schemas/OAuth2Provider'
|
||||
$ref: '#/components/schemas/Provider'
|
||||
user:
|
||||
$ref: '#/components/schemas/User'
|
||||
is_expired:
|
||||
@@ -57261,7 +57261,7 @@ components:
|
||||
readOnly: true
|
||||
title: ID
|
||||
provider:
|
||||
$ref: '#/components/schemas/OAuth2Provider'
|
||||
$ref: '#/components/schemas/Provider'
|
||||
user:
|
||||
$ref: '#/components/schemas/User'
|
||||
is_expired:
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# CVE-2026-40166
|
||||
|
||||
_Reported by [@Colbascov](https://github.com/Colbascov)_
|
||||
|
||||
## Non-admin users can read confidential OAuth provider client secrets via the access token endpoint
|
||||
|
||||
### Summary
|
||||
|
||||
Authenticated non-admin users with at least one OAuth2 access token can retrieve the `client_secret` of confidential OAuth2 providers they have previously authenticated against, via `GET /api/v3/oauth2/access_tokens/`. The API response includes a nested `provider` object containing `client_id` and `client_secret` for providers configured with `client_type: confidential`, which should not be accessible to low-privilege users.
|
||||
|
||||
### Patches
|
||||
|
||||
authentik 2025.12.5 and 2026.2.3 fix this issue; for other versions the workaround can be used.
|
||||
|
||||
### Impact
|
||||
|
||||
Any authenticated non-admin user who has previously completed an OAuth2 flow against a confidential provider — and therefore has an access token object returned by `/api/v3/oauth2/access_tokens/` — can read that provider's `client_secret`. Exposure is limited to providers the user has access to and has logged into at least once; users cannot read secrets for providers they have never authenticated against. This could allow unauthorized reuse of confidential client credentials depending on the provider configuration.
|
||||
|
||||
### Workarounds
|
||||
|
||||
Restrict API access to `/api/v3/oauth2/access_tokens/` for non-admin users, or review and limit which users are permitted to complete OAuth2 flows against confidential providers until a patched version can be applied.
|
||||
|
||||
### For more information
|
||||
|
||||
If you have any questions or comments about this advisory:
|
||||
|
||||
- Email us at [[security@goauthentik.io](mailto:security@goauthentik.io)](mailto:security@goauthentik.io)
|
||||
Reference in New Issue
Block a user