authentik has Insufficient Authorization for several API endpoints
Description
authentik is an open-source Identity Provider. Several API endpoints can be accessed by users without correct authentication/authorization. The main API endpoints affected by this are /api/v3/crypto/certificatekeypairs//view_certificate/, /api/v3/crypto/certificatekeypairs//view_private_key/, and /api/v3/.../used_by/. Note that all of the affected API endpoints require the knowledge of the ID of an object, which especially for certificates is not accessible to an unprivileged user. Additionally the IDs for most objects are UUIDv4, meaning they are not easily guessable/enumerable. authentik 2024.4.4, 2024.6.4 and 2024.8.0 fix this issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
authentik suffers from improper authorization on API endpoints, allowing unauthenticated access to certificate keys and object relationships if the object ID is known.
authentik, an open-source Identity Provider, has a vulnerability in several API endpoints that lack proper authentication and authorization checks [1]. The affected endpoints include /api/v3/crypto/certificatekeypairs//view_certificate/, /api/v3/crypto/certificatekeypairs//view_private_key/, and /api/v3/.../used_by/. The root cause is that the endpoints do not verify whether the requesting user has the necessary permissions to access the requested objects [2] [3].
Exploitation requires knowledge of the object's UUID, which is typically a UUIDv4 and not easily guessable. However, an attacker who obtains a valid UUID through information leakage or other means can access these endpoints without authentication. The attack is network-based and does not require any privileges [1].
If exploited, an attacker can view certificate details, download private keys, and inspect the relationships (used_by) of objects, potentially leading to further compromise of the identity provider and its associated services [1].
The vulnerability is fixed in authentik versions 2024.4.4, 2024.6.4, and 2024.8.0. Users are advised to upgrade to these versions or later [1] [2] [3].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
goauthentik.ioGo | >= 2024.6.0-rc1, < 2024.6.4 | 2024.6.4 |
goauthentik.ioGo | < 2024.4.4 | 2024.4.4 |
Affected products
3- osv-coords2 versions
< 2024.4.4+ 1 more
- (no CPE)range: < 2024.4.4
- (no CPE)range: >= 2024.6.0-rc1, < 2024.6.4
- goauthentik/authentikv5Range: < 2024.4.4
Patches
2359b343f5152security: fix CVE-2024-42490 (cherry-pick #11022) (#11025)
7 files changed · +101 −5
authentik/core/api/used_by.py+2 −1 modified@@ -14,6 +14,7 @@ from rest_framework.response import Response from authentik.core.api.utils import PassiveSerializer +from authentik.rbac.filters import ObjectFilter class DeleteAction(Enum): @@ -53,7 +54,7 @@ class UsedByMixin: @extend_schema( responses={200: UsedBySerializer(many=True)}, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def used_by(self, request: Request, *args, **kwargs) -> Response: """Get a list of all objects that use this object""" model: Model = self.get_object()
authentik/crypto/api.py+3 −2 modified@@ -35,6 +35,7 @@ from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction from authentik.rbac.decorators import permission_required +from authentik.rbac.filters import ObjectFilter LOGGER = get_logger() @@ -265,7 +266,7 @@ def generate(self, request: Request) -> Response: ], responses={200: CertificateDataSerializer(many=False)}, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def view_certificate(self, request: Request, pk: str) -> Response: """Return certificate-key pairs certificate and log access""" certificate: CertificateKeyPair = self.get_object() @@ -295,7 +296,7 @@ def view_certificate(self, request: Request, pk: str) -> Response: ], responses={200: CertificateDataSerializer(many=False)}, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def view_private_key(self, request: Request, pk: str) -> Response: """Return certificate-key pairs private key and log access""" certificate: CertificateKeyPair = self.get_object()
authentik/crypto/tests.py+60 −0 modified@@ -214,6 +214,46 @@ def test_private_key_download(self): self.assertEqual(200, response.status_code) self.assertIn("Content-Disposition", response) + def test_certificate_download_denied(self): + """Test certificate export (download)""" + self.client.logout() + keypair = create_test_cert() + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-certificate", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(403, response.status_code) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-certificate", + kwargs={"pk": keypair.pk}, + ), + data={"download": True}, + ) + self.assertEqual(403, response.status_code) + + def test_private_key_download_denied(self): + """Test private_key export (download)""" + self.client.logout() + keypair = create_test_cert() + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-private-key", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(403, response.status_code) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-private-key", + kwargs={"pk": keypair.pk}, + ), + data={"download": True}, + ) + self.assertEqual(403, response.status_code) + def test_used_by(self): """Test used_by endpoint""" self.client.force_login(create_test_admin_user()) @@ -246,6 +286,26 @@ def test_used_by(self): ], ) + def test_used_by_denied(self): + """Test used_by endpoint""" + self.client.logout() + keypair = create_test_cert() + OAuth2Provider.objects.create( + name=generate_id(), + client_id="test", + client_secret=generate_key(), + authorization_flow=create_test_flow(), + redirect_uris="http://localhost", + signing_key=keypair, + ) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-used-by", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(403, response.status_code) + def test_discovery(self): """Test certificate discovery""" name = generate_id()
authentik/flows/api/flows.py+2 −1 modified@@ -37,6 +37,7 @@ ) from authentik.lib.views import bad_request_message from authentik.rbac.decorators import permission_required +from authentik.rbac.filters import ObjectFilter LOGGER = get_logger() @@ -281,7 +282,7 @@ def set_background_url(self, request: Request, slug: str): 400: OpenApiResponse(description="Flow not applicable"), }, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def execute(self, request: Request, slug: str): """Execute flow for current user""" # Because we pre-plan the flow here, and not in the planner, we need to manually clear
authentik/outposts/api/service_connections.py+2 −1 modified@@ -26,6 +26,7 @@ KubernetesServiceConnection, OutpostServiceConnection, ) +from authentik.rbac.filters import ObjectFilter class ServiceConnectionSerializer(ModelSerializer, MetaNameSerializer): @@ -75,7 +76,7 @@ class ServiceConnectionViewSet( filterset_fields = ["name"] @extend_schema(responses={200: ServiceConnectionStateSerializer(many=False)}) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def state(self, request: Request, pk: str) -> Response: """Get the service connection's state""" connection = self.get_object()
website/docs/security/CVE-2024-42490.md+31 −0 added@@ -0,0 +1,31 @@ +# CVE-2024-42490 + +_Reported by [@m2a2](https://github.com/m2a2)_ + +## Improper Authorization for Token modification + +### Summary + +Several API endpoints can be accessed by users without correct authentication/authorization. + +The main API endpoints affected by this: + +- `/api/v3/crypto/certificatekeypairs/<uuid>/view_certificate/` +- `/api/v3/crypto/certificatekeypairs/<uuid>/view_private_key/` +- `/api/v3/.../used_by/` + +Note that all of the affected API endpoints require the knowledge of the ID of an object, which especially for certificates is not accessible to an unprivileged user. Additionally the IDs for most objects are UUIDv4, meaning they are not easily guessable/enumerable. + +### Patches + +authentik 2024.4.4, 2024.6.4 and 2024.8.0 fix this issue. + +### Workarounds + +Access to the API endpoints can be blocked at a Reverse-proxy/Load balancer level to prevent this issue from being exploited. + +### For more information + +If you have any questions or comments about this advisory: + +- Email us at [security@goauthentik.io](mailto:security@goauthentik.io)
website/sidebars.js+1 −0 modified@@ -511,6 +511,7 @@ const docsSidebar = { items: [ "security/security-hardening", "security/policy", + "security/CVE-2024-42490", "security/CVE-2024-38371", "security/CVE-2024-37905", "security/CVE-2024-23647",
19318d4c00bbsecurity: fix CVE-2024-42490 (cherry-pick #11022) (#11024)
7 files changed · +101 −5
authentik/core/api/used_by.py+2 −1 modified@@ -14,6 +14,7 @@ from rest_framework.response import Response from authentik.core.api.utils import PassiveSerializer +from authentik.rbac.filters import ObjectFilter class DeleteAction(Enum): @@ -53,7 +54,7 @@ class UsedByMixin: @extend_schema( responses={200: UsedBySerializer(many=True)}, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def used_by(self, request: Request, *args, **kwargs) -> Response: """Get a list of all objects that use this object""" model: Model = self.get_object()
authentik/crypto/api.py+3 −2 modified@@ -36,6 +36,7 @@ from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction from authentik.rbac.decorators import permission_required +from authentik.rbac.filters import ObjectFilter LOGGER = get_logger() @@ -266,7 +267,7 @@ def generate(self, request: Request) -> Response: ], responses={200: CertificateDataSerializer(many=False)}, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def view_certificate(self, request: Request, pk: str) -> Response: """Return certificate-key pairs certificate and log access""" certificate: CertificateKeyPair = self.get_object() @@ -296,7 +297,7 @@ def view_certificate(self, request: Request, pk: str) -> Response: ], responses={200: CertificateDataSerializer(many=False)}, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def view_private_key(self, request: Request, pk: str) -> Response: """Return certificate-key pairs private key and log access""" certificate: CertificateKeyPair = self.get_object()
authentik/crypto/tests.py+60 −0 modified@@ -214,6 +214,46 @@ def test_private_key_download(self): self.assertEqual(200, response.status_code) self.assertIn("Content-Disposition", response) + def test_certificate_download_denied(self): + """Test certificate export (download)""" + self.client.logout() + keypair = create_test_cert() + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-certificate", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(403, response.status_code) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-certificate", + kwargs={"pk": keypair.pk}, + ), + data={"download": True}, + ) + self.assertEqual(403, response.status_code) + + def test_private_key_download_denied(self): + """Test private_key export (download)""" + self.client.logout() + keypair = create_test_cert() + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-private-key", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(403, response.status_code) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-view-private-key", + kwargs={"pk": keypair.pk}, + ), + data={"download": True}, + ) + self.assertEqual(403, response.status_code) + def test_used_by(self): """Test used_by endpoint""" self.client.force_login(create_test_admin_user()) @@ -246,6 +286,26 @@ def test_used_by(self): ], ) + def test_used_by_denied(self): + """Test used_by endpoint""" + self.client.logout() + keypair = create_test_cert() + OAuth2Provider.objects.create( + name=generate_id(), + client_id="test", + client_secret=generate_key(), + authorization_flow=create_test_flow(), + redirect_uris="http://localhost", + signing_key=keypair, + ) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-used-by", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(403, response.status_code) + def test_discovery(self): """Test certificate discovery""" name = generate_id()
authentik/flows/api/flows.py+2 −1 modified@@ -33,6 +33,7 @@ ) from authentik.lib.views import bad_request_message from authentik.rbac.decorators import permission_required +from authentik.rbac.filters import ObjectFilter LOGGER = get_logger() @@ -277,7 +278,7 @@ def set_background_url(self, request: Request, slug: str): 400: OpenApiResponse(description="Flow not applicable"), }, ) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def execute(self, request: Request, slug: str): """Execute flow for current user""" # Because we pre-plan the flow here, and not in the planner, we need to manually clear
authentik/outposts/api/service_connections.py+2 −1 modified@@ -23,6 +23,7 @@ KubernetesServiceConnection, OutpostServiceConnection, ) +from authentik.rbac.filters import ObjectFilter class ServiceConnectionSerializer(ModelSerializer, MetaNameSerializer): @@ -88,7 +89,7 @@ def types(self, request: Request) -> Response: return Response(TypeCreateSerializer(data, many=True).data) @extend_schema(responses={200: ServiceConnectionStateSerializer(many=False)}) - @action(detail=True, pagination_class=None, filter_backends=[]) + @action(detail=True, pagination_class=None, filter_backends=[ObjectFilter]) def state(self, request: Request, pk: str) -> Response: """Get the service connection's state""" connection = self.get_object()
website/docs/security/CVE-2024-42490.md+31 −0 added@@ -0,0 +1,31 @@ +# CVE-2024-42490 + +_Reported by [@m2a2](https://github.com/m2a2)_ + +## Improper Authorization for Token modification + +### Summary + +Several API endpoints can be accessed by users without correct authentication/authorization. + +The main API endpoints affected by this: + +- `/api/v3/crypto/certificatekeypairs/<uuid>/view_certificate/` +- `/api/v3/crypto/certificatekeypairs/<uuid>/view_private_key/` +- `/api/v3/.../used_by/` + +Note that all of the affected API endpoints require the knowledge of the ID of an object, which especially for certificates is not accessible to an unprivileged user. Additionally the IDs for most objects are UUIDv4, meaning they are not easily guessable/enumerable. + +### Patches + +authentik 2024.4.4, 2024.6.4 and 2024.8.0 fix this issue. + +### Workarounds + +Access to the API endpoints can be blocked at a Reverse-proxy/Load balancer level to prevent this issue from being exploited. + +### For more information + +If you have any questions or comments about this advisory: + +- Email us at [security@goauthentik.io](mailto:security@goauthentik.io)
website/sidebars.js+1 −0 modified@@ -436,6 +436,7 @@ const docsSidebar = { }, items: [ "security/policy", + "security/CVE-2024-42490", "security/CVE-2024-38371", "security/CVE-2024-37905", "security/CVE-2024-23647",
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-qxqc-27pr-wgc8ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-42490ghsaADVISORY
- github.com/goauthentik/authentik/commit/19318d4c00bb02c4ec3c4f8f15ac2e1dbe8d846cghsax_refsource_MISCWEB
- github.com/goauthentik/authentik/commit/359b343f51524342a5ca03828e7c975a1d654b11ghsax_refsource_MISCWEB
- github.com/goauthentik/authentik/security/advisories/GHSA-qxqc-27pr-wgc8ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.