CVE-2024-32470: Insufficient Information (NVD-CWE-noinfo)
value: Tolgee is an open-source localization platform. When API key created by admin user is used it bypasses the permission check at all. This error was introduced in v3.57.2 and immediately fixed in v3.57.4. 
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-04-18T15:15Z
Repository: https://github.com/tolgee/tolgee-platform
Language: Kotlin
Files changed: backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt, backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt
Commit date: 2024-04-17 17:35:07 +0200
Commit message: fix: Admin should not bypass auth when using API key (#2257)


Diff: diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt b/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt
index a207b4bdc..a10f4fcd4 100644
--- a/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt
+++ b/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt
@@ -88,11 +88,11 @@ class ProjectAuthorizationInterceptor(
     }
 
     val missingScopes = getMissingScopes(requiredScopes, scopes.toSet())
 
     if (missingScopes.isNotEmpty()) {
-      if (!isAdmin) {
+      if (!isAdmin || authenticationFacade.isProjectApiKeyAuth) {
         logger.debug(
           "Rejecting access to proj#{} for user#{} - Insufficient permissions",
           project.id,
           userId,
         )
diff --git a/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt b/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt
index 7642e88ea..b707dd3fa 100644
--- a/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt
+++ b/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt
@@ -23,10 +23,11 @@ import io.tolgee.dtos.cacheable.ProjectDto
 import io.tolgee.dtos.cacheable.UserAccountDto
 import io.tolgee.fixtures.andIsForbidden
 import io.tolgee.fixtures.andIsNotFound
 import io.tolgee.fixtures.andIsOk
 import io.tolgee.model.Project
+import io.tolgee.model.UserAccount
 import io.tolgee.model.enums.Scope
 import io.tolgee.security.OrganizationHolder
 import io.tolgee.security.ProjectHolder
 import io.tolgee.security.ProjectNotSelectedException
 import io.tolgee.security.RequestContextService
@@ -154,10 +155,26 @@ class ProjectAuthorizationInterceptorTest {
       .thenReturn(setOf(Scope.KEYS_CREATE))
 
     mockMvc.perform(MockMvcRequestBuilders.get("/v2/projects/1337/requires-single-scope")).andIsOk
   }
 
+  @Test
+  fun `rejects access if the user is admin and authorizes with API key`() {
+    Mockito.`when`(authenticationFacade.isApiAuthentication).thenReturn(false)
+    Mockito.`when`(userAccount.role).thenReturn(UserAccount.Role.ADMIN)
+
+    Mockito.`when`(securityService.getCurrentPermittedScopes(1337L))
+      .thenReturn(setOf(Scope.KEYS_VIEW))
+
+    mockMvc.perform(MockMvcRequestBuilders.get("/v2/projects/1337/requires-single-scope")).andIsOk
+
+    Mockito.`when`(authenticationFacade.isProjectApiKeyAuth).thenReturn(true)
+    Mockito.`when`(userAccount.role).thenReturn(UserAccount.Role.ADMIN)
+
+    mockMvc.perform(MockMvcRequestBuilders.get("/v2/projects/1337/requires-single-scope")).andIsForbidden
+  }
+
   @Test
   fun `rejects access if the user does not have the required scope (multiple scopes)`() {
     Mockito.`when`(securityService.getCurrentPermittedScopes(1337L))
       .thenReturn(setOf(Scope.KEYS_CREATE))
 

Vulnerable code:       if (!isAdmin) {
Fixed code:       if (!isAdmin || authenticationFacade.isProjectApiKeyAuth) {
import io.tolgee.model.UserAccount
  @Test
  fun `rejects access if the user is admin and authorizes with API key`() {
    Mockito.`when`(authenticationFacade.isApiAuthentication).thenReturn(false)
    Mockito.`when`(userAccount.role).thenReturn(UserAccount.Role.ADMIN)

    Mockito.`when`(securityService.getCurrentPermittedScopes(1337L))
      .thenReturn(setOf(Scope.KEYS_VIEW))

    mockMvc.perform(MockMvcRequestBuilders.get("/v2/projects/1337/requires-single-scope")).andIsOk

    Mockito.`when`(authenticationFacade.isProjectApiKeyAuth).thenReturn(true)
    Mockito.`when`(userAccount.role).thenReturn(UserAccount.Role.ADMIN)

    mockMvc.perform(MockMvcRequestBuilders.get("/v2/projects/1337/requires-single-scope")).andIsForbidden
  }