VYPR
High severity8.3OSV Advisory· Published May 30, 2025· Updated Apr 15, 2026

CVE-2025-48881

CVE-2025-48881

Description

Valtimo is a platform for Business Process Automation. In versions starting from 11.0.0.RELEASE to 11.3.3.RELEASE and 12.0.0.RELEASE to 12.12.0.RELEASE, all objects for which an object-management configuration exists can be listed, viewed, edited, created or deleted by unauthorised users. If object-urls are exposed via other channels, the contents of these objects can be viewed independent of object-management configurations. This issue has been patched in version 12.13.0.RELEASE. A workaround for this issue involves overriding the endpoint security as defined in ObjectenApiHttpSecurityConfigurer and ObjectManagementHttpSecurityConfigurer. Depending on the implementation, this could result in loss of functionality.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.ritense.valtimo:objecten-apiMaven
>= 11.0.0.RELEASE, <= 11.3.3.RELEASE
com.ritense.valtimo:object-managementMaven
>= 11.0.0.RELEASE, <= 11.3.3.RELEASE
com.ritense.valtimo:object-managementMaven
>= 12.0.0.RELEASE, < 12.13.0.RELEASE12.13.0.RELEASE
com.ritense.valtimo:objecten-apiMaven
>= 12.0.0.RELEASE, < 12.13.0.RELEASE12.13.0.RELEASE

Affected products

1

Patches

2
6ab04b30d3da

Added permission check for objecten api objects (#1875)

17 files changed · +383 81
  • app/gzac/.env.properties+1 1 modified
    @@ -14,7 +14,7 @@ CATALOGI_API_URL=http://localhost:8001/catalogi/api/v1/
     DOCUMENTEN_API_URL=http://localhost:8001/documenten/api/v1/
     NOTIFICATIES_API_URL=http://localhost:8002/api/v1/
     OBJECTEN_API_URL=http://localhost:8010/api/v2/
    -OBJECTTYPEN_API_URL=http://localhost:8011/api/v1/
    +OBJECTTYPEN_API_URL=http://localhost:8011/api/v2/
     
     OPEN_ZAAK_CLIENT_ID=valtimo_client
     OPEN_ZAAK_CLIENT_SECRET=e09b8bc5-5831-4618-ab28-41411304309d
    
  • app/gzac/src/main/resources/config/application.yml+2 0 modified
    @@ -250,6 +250,8 @@ valtimo:
                 polling.rate: "PT1M"
     
         authorization:
    +        objectenapi:
    +            enabled: true
             dashboard:
                 enabled: true
             zgwDocuments:
    
  • app/gzac/src/main/resources/config/pbac/object.permission.json+30 0 added
    @@ -0,0 +1,30 @@
    +{
    +    "changesetId": "object-admin-v1",
    +    "permissions": [
    +        {
    +            "resourceType": "com.ritense.objectenapi.security.Object",
    +            "action": "create",
    +            "roleKey": "ROLE_ADMIN"
    +        },
    +        {
    +            "resourceType": "com.ritense.objectenapi.security.Object",
    +            "action": "modify",
    +            "roleKey": "ROLE_ADMIN"
    +        },
    +        {
    +            "resourceType": "com.ritense.objectenapi.security.Object",
    +            "action": "view",
    +            "roleKey": "ROLE_ADMIN"
    +        },
    +        {
    +            "resourceType": "com.ritense.objectenapi.security.Object",
    +            "action": "view_list",
    +            "roleKey": "ROLE_ADMIN"
    +        },
    +        {
    +            "resourceType": "com.ritense.objectenapi.security.Object",
    +            "action": "delete",
    +            "roleKey": "ROLE_ADMIN"
    +        }
    +    ]
    +}
    
  • zgw/objecten-api/build.gradle+1 0 modified
    @@ -30,6 +30,7 @@ dockerCompose {
     }
     
     dependencies {
    +    implementation project(':authorization')
         implementation project(':plugin')
         implementation project(':contract')
         implementation project(':document')
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/client/ObjectenApiClient.kt+88 1 modified
    @@ -17,13 +17,17 @@
     package com.ritense.objectenapi.client
     
     import com.fasterxml.jackson.databind.ObjectMapper
    +import com.ritense.authorization.AuthorizationService
    +import com.ritense.authorization.request.EntityAuthorizationRequest
     import com.ritense.objectenapi.ObjectenApiAuthentication
     import com.ritense.objectenapi.event.ObjectCreated
     import com.ritense.objectenapi.event.ObjectDeleted
     import com.ritense.objectenapi.event.ObjectPatched
     import com.ritense.objectenapi.event.ObjectUpdated
     import com.ritense.objectenapi.event.ObjectViewed
     import com.ritense.objectenapi.event.ObjectsListed
    +import com.ritense.objectenapi.security.Object
    +import com.ritense.objectenapi.security.ObjectActionProvider
     import com.ritense.outbox.OutboxService
     import org.springframework.data.domain.Pageable
     import org.springframework.http.HttpStatus
    @@ -35,7 +39,9 @@ import java.net.URI
     class ObjectenApiClient(
         private val restClientBuilder: RestClient.Builder,
         private val outboxService: OutboxService,
    -    private val objectMapper: ObjectMapper
    +    private val objectMapper: ObjectMapper,
    +    private val authorizationService: AuthorizationService,
    +    private val authorizationEnabled: Boolean,
     ) {
     
         fun getObject(
    @@ -48,6 +54,16 @@ class ObjectenApiClient(
                 .retrieve()
                 .body<ObjectWrapper>()!!
     
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.VIEW,
    +                    Object()
    +                )
    +            )
    +        }
    +
             outboxService.send {
                 ObjectViewed(
                     result.url.toString(),
    @@ -74,6 +90,16 @@ class ObjectenApiClient(
                 .retrieve()
                 .body<ObjectRecord>()!!
     
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.VIEW,
    +                    Object()
    +                )
    +            )
    +        }
    +
             outboxService.send {
                 ObjectViewed(
                     objectUrl.toString(),
    @@ -112,6 +138,16 @@ class ObjectenApiClient(
                 .retrieve()
                 .body<ObjectsList>()!!
     
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.VIEW_LIST,
    +                    Object()
    +                )
    +            )
    +        }
    +
             outboxService.send {
                 ObjectsListed(
                     objectMapper.valueToTree(result.results)
    @@ -151,6 +187,16 @@ class ObjectenApiClient(
                 .retrieve()
                 .body<ObjectsList>()!!
     
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.VIEW_LIST,
    +                    Object()
    +                )
    +            )
    +        }
    +
             outboxService.send {
                 ObjectsListed(
                     objectMapper.valueToTree(result.results)
    @@ -164,6 +210,16 @@ class ObjectenApiClient(
             objectsApiUrl: URI,
             objectRequest: ObjectRequest
         ): ObjectWrapper {
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.CREATE,
    +                    Object()
    +                )
    +            )
    +        }
    +
             val result = buildRestClient(authentication, objectsApiUrl.toASCIIString())
                 .post()
                 .uri("objects")
    @@ -187,6 +243,17 @@ class ObjectenApiClient(
             objectUrl: URI,
             objectRequest: ObjectRequest
         ): ObjectWrapper {
    +
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.MODIFY,
    +                    Object()
    +                )
    +            )
    +        }
    +
             val result = buildRestClient(authentication)
                 .patch()
                 .uri(objectUrl)
    @@ -209,6 +276,16 @@ class ObjectenApiClient(
             objectUrl: URI,
             objectRequest: ObjectRequest
         ): ObjectWrapper {
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.MODIFY,
    +                    Object()
    +                )
    +            )
    +        }
    +
             val result = buildRestClient(authentication)
                 .put()
                 .uri(objectUrl)
    @@ -227,6 +304,16 @@ class ObjectenApiClient(
         }
     
         fun deleteObject(authentication: ObjectenApiAuthentication, objectUrl: URI): HttpStatus {
    +        if (authorizationEnabled) {
    +            authorizationService.requirePermission(
    +                EntityAuthorizationRequest(
    +                    Object::class.java,
    +                    ObjectActionProvider.DELETE,
    +                    Object()
    +                )
    +            )
    +        }
    +
             val result = buildRestClient(authentication)
                 .delete()
                 .uri(objectUrl)
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/listener/ZaakObjectListener.kt+22 19 modified
    @@ -19,6 +19,7 @@ package com.ritense.objectenapi.listener
     import com.fasterxml.jackson.databind.node.NullNode
     import com.fasterxml.jackson.databind.node.ObjectNode
     import com.fasterxml.jackson.databind.node.ValueNode
    +import com.ritense.authorization.AuthorizationContext.Companion.runWithoutAuthorization
     import com.ritense.objectenapi.ObjectenApiPlugin
     import com.ritense.objectenapi.client.ObjectRecord
     import com.ritense.objectenapi.client.ObjectRequest
    @@ -40,26 +41,28 @@ class ZaakObjectListener(
     ) {
         @EventListener(ExternalDataSubmittedEvent::class)
         fun handle(event: ExternalDataSubmittedEvent) {
    -        event.data[ZaakObjectConstants.ZAAKOBJECT_PREFIX]?.let { zaakObjectMap ->
    -            logger.debug { "Received external data for zaak object, updating the following properties: ${zaakObjectMap.keys.joinToString() }" }
    -            zaakObjectMap.entries.map { entry ->
    -                RequestedField(
    -                    entry.key, entry.value
    -                )
    -            }.groupBy { requestedField ->
    -                requestedField.objectType
    -            }.forEach { objectTypeGroup ->
    -                val zaakObject = zaakObjectService.getZaakObjectOfTypeByName(event.documentId, objectTypeGroup.key)
    -                objectTypeGroup.value.forEach { requestedField ->
    -                    logger.trace { "Updating field ${requestedField.path} with value ${requestedField.value} in object '${zaakObject.url}' of type '${objectTypeGroup.key}'" }
    -                    // For each requestedField update the value in the zaakObject record data
    -                    val startPath = requestedField.path.substring(1)
    -                    val newValueNode = getValueNode(requestedField.value)
    -                    findAndReplaceJsonPath(zaakObject.record.data!! as ObjectNode, startPath, newValueNode)
    +        runWithoutAuthorization {
    +            event.data[ZaakObjectConstants.ZAAKOBJECT_PREFIX]?.let { zaakObjectMap ->
    +                logger.debug { "Received external data for zaak object, updating the following properties: ${zaakObjectMap.keys.joinToString()}" }
    +                zaakObjectMap.entries.map { entry ->
    +                    RequestedField(
    +                        entry.key, entry.value
    +                    )
    +                }.groupBy { requestedField ->
    +                    requestedField.objectType
    +                }.forEach { objectTypeGroup ->
    +                    val zaakObject = zaakObjectService.getZaakObjectOfTypeByName(event.documentId, objectTypeGroup.key)
    +                    objectTypeGroup.value.forEach { requestedField ->
    +                        logger.trace { "Updating field ${requestedField.path} with value ${requestedField.value} in object '${zaakObject.url}' of type '${objectTypeGroup.key}'" }
    +                        // For each requestedField update the value in the zaakObject record data
    +                        val startPath = requestedField.path.substring(1)
    +                        val newValueNode = getValueNode(requestedField.value)
    +                        findAndReplaceJsonPath(zaakObject.record.data!! as ObjectNode, startPath, newValueNode)
    +                    }
    +
    +                    // The zaakObject.record.data has now been updated with the new values, update the object in the objecten api
    +                    updateObject(zaakObject.url, event.documentId, objectTypeGroup.key, zaakObject.record)
                     }
    -
    -                // The zaakObject.record.data has now been updated with the new values, update the object in the objecten api
    -                updateObject(zaakObject.url, event.documentId, objectTypeGroup.key, zaakObject.record)
                 }
             }
         }
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/ObjectenApiAutoConfiguration.kt+29 6 modified
    @@ -17,11 +17,13 @@
     package com.ritense.objectenapi
     
     import com.fasterxml.jackson.databind.ObjectMapper
    +import com.ritense.authorization.AuthorizationService
     import com.ritense.form.service.FormDefinitionService
     import com.ritense.objectenapi.client.ObjectenApiClient
     import com.ritense.objectenapi.listener.ZaakObjectListener
     import com.ritense.objectenapi.management.ErrorObjectManagementInfoProvider
     import com.ritense.objectenapi.management.ObjectManagementInfoProvider
    +import com.ritense.objectenapi.security.ObjectSpecificationFactory
     import com.ritense.objectenapi.security.ObjectenApiHttpSecurityConfigurer
     import com.ritense.objectenapi.service.ZaakObjectDataResolver
     import com.ritense.objectenapi.service.ZaakObjectService
    @@ -32,6 +34,8 @@ import com.ritense.outbox.OutboxService
     import com.ritense.plugin.service.PluginService
     import com.ritense.processdocument.service.ProcessDocumentService
     import com.ritense.zakenapi.ZaakUrlProvider
    +import mu.KotlinLogging
    +import org.springframework.beans.factory.annotation.Value
     import org.springframework.boot.autoconfigure.AutoConfiguration
     import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
     import org.springframework.context.annotation.Bean
    @@ -57,12 +61,21 @@ class ObjectenApiAutoConfiguration {
         fun objectenApiClient(
             restClientBuilder: RestClient.Builder,
             outboxService: OutboxService,
    -        objectMapper: ObjectMapper
    -    ) = ObjectenApiClient(
    -        restClientBuilder,
    -        outboxService,
    -        objectMapper
    -    )
    +        objectMapper: ObjectMapper,
    +        authorizationService: AuthorizationService,
    +        @Value("\${valtimo.authorization.objectenapi.enabled:true}") authorizationEnabled: Boolean
    +    ): ObjectenApiClient {
    +        if (!authorizationEnabled) {
    +            logger.warn { "Objecten API authorization is disabled. This is a potential security issue. The option to disable this will be removed with Valtimo 13." }
    +        }
    +        return ObjectenApiClient(
    +            restClientBuilder,
    +            outboxService,
    +            objectMapper,
    +            authorizationService,
    +            authorizationEnabled
    +        )
    +    }
     
         @Bean
         fun objectenApiPluginFactory(
    @@ -131,4 +144,14 @@ class ObjectenApiAutoConfiguration {
         fun errorObjectManagementInfoProvider(): ObjectManagementInfoProvider {
             return ErrorObjectManagementInfoProvider()
         }
    +
    +    @Bean
    +    @ConditionalOnMissingBean(ObjectSpecificationFactory::class)
    +    fun objectSpecificationFactory(): ObjectSpecificationFactory {
    +        return ObjectSpecificationFactory()
    +    }
    +
    +    companion object {
    +        val logger = KotlinLogging.logger {}
    +    }
     }
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/security/ObjectActionProvider.kt+34 0 added
    @@ -0,0 +1,34 @@
    +/*
    + * Copyright 2015-2025 Ritense BV, the Netherlands.
    + *
    + * Licensed under EUPL, Version 1.2 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" basis,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package com.ritense.objectenapi.security
    +
    +import com.ritense.authorization.Action
    +import com.ritense.authorization.ResourceActionProvider
    +
    +class ObjectActionProvider : ResourceActionProvider<Object> {
    +    override fun getAvailableActions(): List<Action<Object>> {
    +        return listOf(VIEW, VIEW_LIST, CREATE, MODIFY, DELETE)
    +    }
    +
    +    companion object {
    +        var VIEW = Action<Object>(Action.VIEW)
    +        var VIEW_LIST = Action<Object>(Action.VIEW_LIST)
    +        var CREATE = Action<Object>(Action.CREATE)
    +        var MODIFY = Action<Object>(Action.MODIFY)
    +        var DELETE = Action<Object>(Action.DELETE)
    +    }
    +}
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/security/Object.kt+22 0 added
    @@ -0,0 +1,22 @@
    +/*
    + * Copyright 2015-2025 Ritense BV, the Netherlands.
    + *
    + * Licensed under EUPL, Version 1.2 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" basis,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package com.ritense.objectenapi.security
    +
    +/*
    + * This class is a placeholder for an Objecten API Object used in permission checks.
    + */
    +class Object()
    \ No newline at end of file
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/security/ObjectSpecificationFactory.kt+40 0 added
    @@ -0,0 +1,40 @@
    +/*
    + * Copyright 2015-2025 Ritense BV, the Netherlands.
    + *
    + * Licensed under EUPL, Version 1.2 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" basis,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package com.ritense.objectenapi.security
    +
    +import com.ritense.authorization.permission.Permission
    +import com.ritense.authorization.request.AuthorizationRequest
    +import com.ritense.authorization.specification.AuthorizationSpecification
    +import com.ritense.authorization.specification.AuthorizationSpecificationFactory
    +import com.ritense.valtimo.contract.annotation.SkipComponentScan
    +import org.springframework.stereotype.Component
    +
    +@Component
    +@SkipComponentScan
    +class ObjectSpecificationFactory : AuthorizationSpecificationFactory<Object> {
    +
    +    override fun create(
    +        request: AuthorizationRequest<Object>,
    +        permissions: List<Permission>
    +    ): AuthorizationSpecification<Object> {
    +        return ObjectSpecification(request, permissions)
    +    }
    +
    +    override fun canCreate(request: AuthorizationRequest<*>, permissions: List<Permission>): Boolean {
    +        return Object::class.java == request.resourceType
    +    }
    +}
    \ No newline at end of file
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/security/ObjectSpecification.kt+44 0 added
    @@ -0,0 +1,44 @@
    +/*
    + * Copyright 2015-2025 Ritense BV, the Netherlands.
    + *
    + * Licensed under EUPL, Version 1.2 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" basis,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package com.ritense.objectenapi.security
    +
    +import com.ritense.authorization.permission.Permission
    +import com.ritense.authorization.request.AuthorizationRequest
    +import com.ritense.authorization.specification.AuthorizationSpecification
    +import jakarta.persistence.criteria.AbstractQuery
    +import jakarta.persistence.criteria.CriteriaBuilder
    +import jakarta.persistence.criteria.Predicate
    +import jakarta.persistence.criteria.Root
    +
    +class ObjectSpecification(
    +    authRequest: AuthorizationRequest<Object>,
    +    permissions: List<Permission>,
    +) : AuthorizationSpecification<Object>(authRequest, permissions) {
    +
    +    override fun toPredicate(
    +        root: Root<Object>,
    +        query: AbstractQuery<*>,
    +        criteriaBuilder: CriteriaBuilder
    +    ): Predicate {
    +        throw NotImplementedError()
    +    }
    +
    +    override fun identifierToEntity(identifier: String): Object {
    +        throw NotImplementedError()
    +    }
    +}
    +
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/service/ZaakObjectDataResolver.kt+9 5 modified
    @@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeType.NUMBER
     import com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT
     import com.fasterxml.jackson.databind.node.JsonNodeType.POJO
     import com.fasterxml.jackson.databind.node.JsonNodeType.STRING
    +import com.ritense.authorization.AuthorizationContext.Companion.runWithoutAuthorization
     import com.ritense.objectenapi.service.ZaakObjectConstants.Companion.ZAAKOBJECT_PREFIX
     import com.ritense.objectenapi.service.ZaakObjectValueResolverFactory.Companion
     import com.ritense.valtimo.contract.form.DataResolvingContext
    @@ -56,11 +57,14 @@ class ZaakObjectDataResolver(
             }.groupBy {
                 it.objectType
             }.forEach{ objectTypeGroup ->
    -            val zaakObject = zaakObjectService.getZaakObjectOfTypeByName(
    -                dataResolvingContext.documentId, objectTypeGroup.key)
    -            val dataAsJsonNode = objectMapper.valueToTree<JsonNode>(zaakObject.record.data)
    -            objectTypeGroup.value.forEach {
    -                results[it.variableName] = extractValue(dataAsJsonNode.at(it.path))
    +            runWithoutAuthorization {
    +                val zaakObject = zaakObjectService.getZaakObjectOfTypeByName(
    +                    dataResolvingContext.documentId, objectTypeGroup.key
    +                )
    +                val dataAsJsonNode = objectMapper.valueToTree<JsonNode>(zaakObject.record.data)
    +                objectTypeGroup.value.forEach {
    +                    results[it.variableName] = extractValue(dataAsJsonNode.at(it.path))
    +                }
                 }
             }
     
    
  • zgw/objecten-api/src/main/kotlin/com/ritense/objectenapi/service/ZaakObjectValueResolverFactory.kt+3 1 modified
    @@ -18,6 +18,7 @@ package com.ritense.objectenapi.service
     
     import com.fasterxml.jackson.databind.JsonNode
     import com.fasterxml.jackson.databind.ObjectMapper
    +import com.ritense.authorization.AuthorizationContext.Companion.runWithoutAuthorization
     import com.ritense.document.domain.impl.JsonSchemaDocument
     import com.ritense.logging.withLoggingContext
     import com.ritense.processdocument.domain.impl.CamundaProcessInstanceId
    @@ -67,8 +68,9 @@ class ZaakObjectValueResolverFactory(
         private fun getZaakData(requestedValue: String, documentId: String): Any? {
             return withLoggingContext(JsonSchemaDocument::class, documentId) {
                 val requestedData = ZaakObjectDataResolver.RequestedData(requestedValue)
    -            val zaakObject =
    +            val zaakObject = runWithoutAuthorization {
                     zaakObjectService.getZaakObjectOfTypeByName(UUID.fromString(documentId), requestedData.objectType)
    +            }
                 val dataAsJsonNode = objectMapper.valueToTree<JsonNode>(zaakObject.record.data)
                 val node = dataAsJsonNode.at(requestedData.path)
                 return@withLoggingContext if (node == null || node.isMissingNode || node.isNull) {
    
  • zgw/objecten-api/src/test/kotlin/com/ritense/objectenapi/client/ObjectenApiClientTest.kt+26 21 modified
    @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.node.TextNode
     import com.fasterxml.jackson.module.kotlin.readValue
     import com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath
     import com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath
    +import com.ritense.authorization.AuthorizationService
     import com.ritense.objectenapi.ObjectenApiAuthentication
     import com.ritense.objectenapi.event.ObjectCreated
     import com.ritense.objectenapi.event.ObjectDeleted
    @@ -46,6 +47,7 @@ import org.junit.jupiter.api.TestInstance
     import org.junit.jupiter.api.assertThrows
     import org.mockito.Mockito
     import org.mockito.kotlin.argumentCaptor
    +import org.mockito.kotlin.mock
     import org.mockito.kotlin.reset
     import org.mockito.kotlin.times
     import org.mockito.kotlin.verify
    @@ -73,13 +75,16 @@ internal class ObjectenApiClientTest {
     
         lateinit var restClientBuilder: RestClient.Builder
     
    +    lateinit var authorizationService: AuthorizationService
    +
         @BeforeAll
         fun setUp() {
             mockApi = MockWebServer()
             mockApi.start()
             objectMapper = MapperSingleton.get()
    -        outboxService = Mockito.mock(OutboxService::class.java)
    +        outboxService = mock()
             restClientBuilder = RestClient.builder()
    +        authorizationService = mock()
         }
     
         @BeforeEach
    @@ -94,7 +99,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send get single object request and parse response`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -161,7 +166,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send get single objectrecord request and parse response`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -222,7 +227,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message on retrieving object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -277,7 +282,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message on failing to retrieve object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             mockApi.enqueue(mockResponse("").setResponseCode(400))
     
    @@ -299,7 +304,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should get objectslist`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -376,7 +381,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message when getting objects by object type url`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -440,7 +445,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message when failing to get objects by object type url`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val eventCapture = argumentCaptor<Supplier<BaseEvent>>()
     
    @@ -466,7 +471,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message when getting objects by object type url with search params`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -531,7 +536,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message when failing to get objects by object type url with search params`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val eventCapture = argumentCaptor<Supplier<BaseEvent>>()
     
    @@ -559,7 +564,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message on creating object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -624,7 +629,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message on failing to create object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             mockApi.enqueue(mockResponse("").setResponseCode(400))
     
    @@ -656,7 +661,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send post request when creating object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -714,7 +719,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send post request with uuid when uuid has been provided when creating object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -774,7 +779,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send patch request`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -865,7 +870,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message on patching object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -930,7 +935,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message on failing to patch object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val eventCapture = argumentCaptor<Supplier<BaseEvent>>()
     
    @@ -962,7 +967,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message on updating object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val responseBody = """
                 {
    @@ -1027,7 +1032,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message on failing to update object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val eventCapture = argumentCaptor<Supplier<BaseEvent>>()
     
    @@ -1059,7 +1064,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should send outbox message on deleting object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val eventCapture = argumentCaptor<Supplier<BaseEvent>>()
     
    @@ -1084,7 +1089,7 @@ internal class ObjectenApiClientTest {
     
         @Test
         fun `should not send outbox message on failing to delete object`() {
    -        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper)
    +        val client = ObjectenApiClient(restClientBuilder, outboxService, objectMapper, authorizationService, false)
     
             val eventCapture = argumentCaptor<Supplier<BaseEvent>>()
     
    
  • zgw/object-management/build.gradle+1 0 modified
    @@ -30,6 +30,7 @@ dockerCompose {
     }
     
     dependencies {
    +    implementation project(':authorization')
         implementation project(':plugin')
         implementation project(':contract')
         implementation project(":web")
    
  • zgw/object-management/src/main/kotlin/com/ritense/objectmanagement/service/ObjectManagementFacade.kt+26 23 modified
    @@ -17,6 +17,7 @@
     package com.ritense.objectmanagement.service
     
     import com.fasterxml.jackson.databind.JsonNode
    +import com.ritense.authorization.AuthorizationContext.Companion.runWithoutAuthorization
     import com.ritense.objectenapi.ObjectenApiPlugin
     import com.ritense.objectenapi.client.ObjectRecord
     import com.ritense.objectenapi.client.ObjectRequest
    @@ -231,20 +232,20 @@ class ObjectManagementFacade(
             val objectUrl = accessObject.objectenApiPlugin.getObjectUrl(uuid)
     
             logger.trace { "Getting object $objectUrl" }
    -        return accessObject.objectenApiPlugin.getObject(objectUrl)
    +        return runWithoutAuthorization { accessObject.objectenApiPlugin.getObject(objectUrl) }
         }
     
         private fun findObjectByUuidAndIndex(accessObject: ObjectManagementAccessObject, uuid: UUID, index: Int): ObjectRecord {
             logger.debug { "Find object by uuid and index accessObject=$accessObject uuid=$uuid index=$index" }
             val objectUrl = accessObject.objectenApiPlugin.getObjectUrl(uuid)
     
             logger.trace { "Getting object $objectUrl" }
    -        return accessObject.objectenApiPlugin.getObjectRecord(objectUrl, index)
    +        return runWithoutAuthorization { accessObject.objectenApiPlugin.getObjectRecord(objectUrl, index) }
         }
     
         private fun findObjectByUri(accessObject: ObjectManagementAccessObject, objectUrl: URI): ObjectWrapper {
             logger.debug { "Getting object $objectUrl" }
    -        return accessObject.objectenApiPlugin.getObject(objectUrl)
    +        return runWithoutAuthorization { accessObject.objectenApiPlugin.getObject(objectUrl) }
         }
     
         private fun findObjectsPaged(
    @@ -255,26 +256,28 @@ class ObjectManagementFacade(
             pageNumber: Int,
             pageSize: Int
         ): ObjectsList {
    -        return if (!searchString.isNullOrBlank()) {
    -            logger.debug { "Getting object page for object type $objectName with search string $searchString" }
    -
    -            accessObject.objectenApiPlugin.getObjectsByObjectTypeIdWithSearchParams(
    -                accessObject.objectTypenApiPlugin.url,
    -                accessObject.objectManagement.objecttypeId,
    -                searchString,
    -                ordering,
    -                PageRequest.of(pageNumber, pageSize)
    -            )
    -        } else {
    -            logger.debug { "Getting object page for object type $objectName" }
    -
    -            accessObject.objectenApiPlugin.getObjectsByObjectTypeId(
    -                accessObject.objectTypenApiPlugin.url,
    -                accessObject.objectenApiPlugin.url,
    -                accessObject.objectManagement.objecttypeId,
    -                ordering,
    -                PageRequest.of(pageNumber, pageSize)
    -            )
    +        return runWithoutAuthorization {
    +            if (!searchString.isNullOrBlank()) {
    +                logger.debug { "Getting object page for object type $objectName with search string $searchString" }
    +
    +                accessObject.objectenApiPlugin.getObjectsByObjectTypeIdWithSearchParams(
    +                    accessObject.objectTypenApiPlugin.url,
    +                    accessObject.objectManagement.objecttypeId,
    +                    searchString,
    +                    ordering,
    +                    PageRequest.of(pageNumber, pageSize)
    +                )
    +            } else {
    +                logger.debug { "Getting object page for object type $objectName" }
    +
    +                accessObject.objectenApiPlugin.getObjectsByObjectTypeId(
    +                    accessObject.objectTypenApiPlugin.url,
    +                    accessObject.objectenApiPlugin.url,
    +                    accessObject.objectManagement.objecttypeId,
    +                    ordering,
    +                    PageRequest.of(pageNumber, pageSize)
    +                )
    +            }
             }
         }
     
    
  • zgw/object-management/src/test/kotlin/com/ritense/objectmanagement/service/ObjectManagementServiceIntTest.kt+5 4 modified
    @@ -19,6 +19,7 @@ package com.ritense.objectmanagement.service
     import com.fasterxml.jackson.databind.JsonNode
     import com.fasterxml.jackson.databind.ObjectMapper
     import com.fasterxml.jackson.databind.node.ObjectNode
    +import com.ritense.authorization.AuthorizationContext.Companion.runWithoutAuthorization
     import com.ritense.objectenapi.client.Comparator.EQUAL_TO
     import com.ritense.objectenapi.client.ObjectSearchParameter
     import com.ritense.objectmanagement.BaseIntegrationTest
    @@ -242,9 +243,9 @@ internal class ObjectManagementServiceIntTest : BaseIntegrationTest() {
             val searchWithConfigRequest =
                 SearchWithConfigRequest(listOf(otherFilters))
     
    -        val objects = objectManagementService.getObjectsWithSearchParams(
    +        val objects = runWithoutAuthorization{ objectManagementService.getObjectsWithSearchParams(
                 searchWithConfigRequest, objectManagement.id, PageRequest.of(0, 10)
    -        )
    +        )}
     
             assertThat(objects.content.size).isEqualTo(1)
             assertThat(objects.first().items[0].key).isEqualTo("property1")
    @@ -294,11 +295,11 @@ internal class ObjectManagementServiceIntTest : BaseIntegrationTest() {
             val objectManagement = objectManagementService.getByTitle("My Object Management")!!
             val searchParameters = listOf(ObjectSearchParameter("property1", EQUAL_TO, "henk"))
     
    -        val objects = objectManagementService.getObjectsWithSearchParams(
    +        val objects = runWithoutAuthorization { objectManagementService.getObjectsWithSearchParams(
                 objectManagement,
                 searchParameters,
                 PageRequest.of(0, 10)
    -        )
    +        )}
     
             assertThat(objects.content.size).isEqualTo(1)
             assertThat(objects.first().url).isEqualTo(URI("https://example.com/123"))
    

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

4

News mentions

0

No linked articles in our index yet.