VYPR
High severityNVD Advisory· Published Jun 13, 2025· Updated Jun 13, 2025

XWiki does not require right warnings for XClass definitions

CVE-2025-49585

Description

XWiki is a generic wiki platform. In versions before 15.10.16, 16.0.0-rc-1 through 16.4.6, and 16.5.0-rc-1 through 16.10.1, when an attacker without script or programming right creates an XClass definition in XWiki (requires edit right), and that same document is later edited by a user with script, admin, or programming right, malicious code could be executed with the rights of the editing user without prior warning. In particular, this concerns custom display code, the script of computed properties and queries in database list properties. Note that warnings before editing documents with dangerous properties have only been introduced in XWiki 15.9, before that version, this was a known issue and the advice was simply to be careful. This has been patched in XWiki 16.10.2, 16.4.7 and 15.10.16 by adding an analysis for the respective XClass properties.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-security-requiredrights-defaultMaven
< 15.10.1615.10.16
org.xwiki.platform:xwiki-platform-security-requiredrights-defaultMaven
>= 16.0.0-rc-1, < 16.4.716.4.7
org.xwiki.platform:xwiki-platform-security-requiredrights-defaultMaven
>= 16.5.0-rc-1, < 16.10.216.10.2

Affected products

1

Patches

1
385bde985cdb

XWIKI-22476: Introduce a required rights analyzer for BaseClass

https://github.com/xwiki/xwiki-platformMichael HamannDec 16, 2024via ghsa
13 files changed · +904 13
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/analyzer/ComputedFieldClassRequiredRightAnalyzer.java+70 0 added
    @@ -0,0 +1,70 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.analyzer;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +
    +import javax.inject.Inject;
    +import javax.inject.Singleton;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.xwiki.component.annotation.Component;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer;
    +import org.xwiki.platform.security.requiredrights.RequiredRightsException;
    +
    +import com.xpn.xwiki.objects.classes.ComputedFieldClass;
    +import com.xpn.xwiki.objects.classes.PropertyClass;
    +
    +/**
    + * Required rights analyzer for {@link ComputedFieldClass}.
    + *
    + * @since 15.10.16
    + * @since 16.4.7
    + * @since 16.10.2
    + * @version $Id$
    + */
    +@Component
    +@Singleton
    +public class ComputedFieldClassRequiredRightAnalyzer implements RequiredRightAnalyzer<ComputedFieldClass>
    +{
    +    @Inject
    +    private XClassWikiContentAnalyzer wikiContentAnalyzer;
    +
    +    @Inject
    +    private RequiredRightAnalyzer<PropertyClass> propertyClassRequiredRightAnalyzer;
    +
    +    @Override
    +    public List<RequiredRightAnalysisResult> analyze(ComputedFieldClass computedFieldClass)
    +        throws RequiredRightsException
    +    {
    +        List<RequiredRightAnalysisResult> results =
    +            new ArrayList<>(this.propertyClassRequiredRightAnalyzer.analyze(computedFieldClass));
    +
    +        if (computedFieldClass != null && StringUtils.isNotBlank(computedFieldClass.getScript())) {
    +            results.addAll(
    +                this.wikiContentAnalyzer.analyzeWikiContent(computedFieldClass.getOwnerDocument().getXClass(),
    +                    computedFieldClass.getScript(), computedFieldClass.getReference()));
    +        }
    +
    +        return results;
    +    }
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/analyzer/DBListClassRequiredRightAnalyzer.java+151 0 added
    @@ -0,0 +1,151 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.analyzer;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +import java.util.Optional;
    +
    +import javax.inject.Inject;
    +import javax.inject.Named;
    +import javax.inject.Singleton;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.commons.lang3.exception.ExceptionUtils;
    +import org.hibernate.engine.spi.NamedQueryDefinition;
    +import org.xwiki.component.annotation.Component;
    +import org.xwiki.platform.security.requiredrights.RequiredRight;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer;
    +import org.xwiki.platform.security.requiredrights.RequiredRightsException;
    +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider;
    +import org.xwiki.query.Query;
    +import org.xwiki.query.QueryBuilder;
    +import org.xwiki.query.QueryException;
    +import org.xwiki.query.hql.internal.HQLStatementValidator;
    +import org.xwiki.velocity.internal.util.VelocityDetector;
    +
    +import com.xpn.xwiki.internal.store.hibernate.HibernateStore;
    +import com.xpn.xwiki.objects.classes.DBListClass;
    +import com.xpn.xwiki.objects.classes.PropertyClass;
    +
    +/**
    + * Required rights analyzer for {@link DBListClass}.
    + *
    + * @since 15.10.16
    + * @since 16.4.7
    + * @since 16.10.2
    + * @version $Id$
    + */
    +@Component
    +@Singleton
    +public class DBListClassRequiredRightAnalyzer implements RequiredRightAnalyzer<DBListClass>
    +{
    +    @Inject
    +    private VelocityDetector velocityDetector;
    +
    +    @Inject
    +    @Named("translation")
    +    private BlockSupplierProvider<String> translationMessageSupplierProvider;
    +
    +    @Inject
    +    @Named("stringCode")
    +    private BlockSupplierProvider<String> stringCodeBlockSupplierProvider;
    +
    +    @Inject
    +    private QueryBuilder<DBListClass> dbListClassQueryBuilder;
    +
    +    @Inject
    +    private HibernateStore hibernate;
    +
    +    @Inject
    +    private HQLStatementValidator hqlStatementValidator;
    +
    +    @Inject
    +    private RequiredRightAnalyzer<PropertyClass> propertyClassRequiredRightAnalyzer;
    +
    +    @Override
    +    public List<RequiredRightAnalysisResult> analyze(DBListClass dbListClass) throws RequiredRightsException
    +    {
    +        List<RequiredRightAnalysisResult> results =
    +            new ArrayList<>(this.propertyClassRequiredRightAnalyzer.analyze(dbListClass));
    +
    +        // Empty HQL is considered safe.
    +        if (dbListClass != null && StringUtils.isNotBlank(dbListClass.getSql())) {
    +            String sql = dbListClass.getSql();
    +            // For Velocity code, we have no idea what the actual query is, but it's the same as Velocity, either
    +            // script (for Velocity) or programming (for Velocity and/or the query).
    +            if (this.velocityDetector.containsVelocityScript(sql)) {
    +                results.add(new RequiredRightAnalysisResult(dbListClass.getReference(),
    +                    this.translationMessageSupplierProvider.get("security.requiredrights.class.dbListVelocity"),
    +                    this.stringCodeBlockSupplierProvider.get(sql),
    +                    RequiredRight.SCRIPT_AND_MAYBE_PROGRAM));
    +            } else {
    +                // For a plain query, do a more thorough analysis by checking the actual query.
    +                try {
    +                    Query query = this.dbListClassQueryBuilder.build(dbListClass);
    +                    results.addAll(validateQuery(dbListClass, query));
    +                } catch (QueryException e) {
    +                    results.add(new RequiredRightAnalysisResult(dbListClass.getReference(),
    +                        this.translationMessageSupplierProvider.get(
    +                            "security.requiredrights.class.errorParsingQuery", ExceptionUtils.getRootCauseMessage(e)),
    +                        this.stringCodeBlockSupplierProvider.get(sql),
    +                        List.of(RequiredRight.MAYBE_PROGRAM))
    +                    );
    +                }
    +            }
    +        }
    +
    +        return results;
    +    }
    +
    +    private List<RequiredRightAnalysisResult> validateQuery(DBListClass dbListClass, Query query) throws QueryException
    +    {
    +        List<RequiredRightAnalysisResult> results = new ArrayList<>();
    +
    +        if (query.isNamed()) {
    +            Optional<String> hqlQuery = getNamedQuery(query);
    +            // Assume unknown named queries are unsafe.
    +            if (hqlQuery.isEmpty() || !this.hqlStatementValidator.isSafe(hqlQuery.get())) {
    +                results.add(new RequiredRightAnalysisResult(dbListClass.getReference(),
    +                    this.translationMessageSupplierProvider.get(
    +                        "security.requiredrights.class.unsafeNamedQuery"),
    +                    this.stringCodeBlockSupplierProvider.get(query.getStatement()),
    +                    List.of(RequiredRight.PROGRAM)
    +                ));
    +            }
    +        } else if (!this.hqlStatementValidator.isSafe(query.getStatement())) {
    +            results.add(new RequiredRightAnalysisResult(dbListClass.getReference(),
    +                this.translationMessageSupplierProvider.get(
    +                    "security.requiredrights.class.unsafeQuery"),
    +                this.stringCodeBlockSupplierProvider.get(query.getStatement()),
    +                List.of(RequiredRight.PROGRAM)
    +            ));
    +        }
    +
    +        return results;
    +    }
    +
    +    private Optional<String> getNamedQuery(Query query)
    +    {
    +        return Optional.ofNullable(this.hibernate.getConfiguration().getNamedQueries().get(query.getStatement()))
    +            .map(NamedQueryDefinition::getQuery);
    +    }
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/analyzer/DefaultBaseClassRequiredRightAnalyzer.java+105 0 added
    @@ -0,0 +1,105 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.analyzer;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +
    +import javax.inject.Inject;
    +import javax.inject.Named;
    +import javax.inject.Provider;
    +import javax.inject.Singleton;
    +
    +import org.apache.commons.lang3.exception.ExceptionUtils;
    +import org.xwiki.component.annotation.Component;
    +import org.xwiki.component.manager.ComponentManager;
    +import org.xwiki.component.util.DefaultParameterizedType;
    +import org.xwiki.model.reference.EntityReference;
    +import org.xwiki.platform.security.requiredrights.RequiredRight;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer;
    +import org.xwiki.platform.security.requiredrights.RequiredRightsException;
    +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider;
    +
    +import com.xpn.xwiki.objects.BaseCollection;
    +import com.xpn.xwiki.objects.classes.BaseClass;
    +import com.xpn.xwiki.objects.classes.PropertyClass;
    +
    +/**
    + * Required rights analyzer for XClass definitions.
    + *
    + * @since 15.10.16
    + * @since 16.4.7
    + * @since 16.10.2
    + * @version $Id$
    + */
    +@Component
    +@Singleton
    +public class DefaultBaseClassRequiredRightAnalyzer implements RequiredRightAnalyzer<BaseClass>
    +{
    +    @Inject
    +    @Named("context")
    +    private Provider<ComponentManager> componentManagerProvider;
    +
    +    @Inject
    +    @Named("translation")
    +    private BlockSupplierProvider<String> translationMessageSupplierProvider;
    +
    +    @Inject
    +    private BlockSupplierProvider<BaseCollection<? extends EntityReference>> baseCollectionBlockSupplierProvider;
    +
    +    @Override
    +    public List<RequiredRightAnalysisResult> analyze(BaseClass xClass) throws RequiredRightsException
    +    {
    +        List<RequiredRightAnalysisResult> results = new ArrayList<>();
    +
    +        // Analyze required rights for XClass definitions. We're mainly concerned about custom displayers and
    +        // database list properties.
    +        for (Object field : xClass.getFieldList()) {
    +            if (field instanceof PropertyClass propertyClass) {
    +                ComponentManager componentManager = this.componentManagerProvider.get();
    +
    +                Class<? super PropertyClass> superClass = PropertyClass.class.getSuperclass();
    +                for (Class<?> clazz = propertyClass.getClass(); !clazz.equals(superClass);
    +                    clazz = clazz.getSuperclass()) {
    +                    DefaultParameterizedType roleType =
    +                        new DefaultParameterizedType(null, RequiredRightAnalyzer.class, clazz);
    +                    if (componentManager.hasComponent(roleType)) {
    +                        try {
    +                            RequiredRightAnalyzer<PropertyClass> analyzer = componentManager.getInstance(roleType);
    +                            results.addAll(analyzer.analyze(propertyClass));
    +                        } catch (Exception e) {
    +                            results.add(new RequiredRightAnalysisResult(propertyClass.getReference(),
    +                                this.translationMessageSupplierProvider.get(
    +                                    "security.requiredrights.class.errorAnalyzingProperty",
    +                                    ExceptionUtils.getRootCauseMessage(e)),
    +                                this.baseCollectionBlockSupplierProvider.get(propertyClass),
    +                                List.of(RequiredRight.MAYBE_PROGRAM)));
    +                        }
    +                        break;
    +                    }
    +                }
    +            }
    +        }
    +
    +        return results;
    +    }
    +
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/analyzer/PropertyClassRequiredRightAnalyzer.java+60 0 added
    @@ -0,0 +1,60 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.analyzer;
    +
    +import java.util.List;
    +
    +import javax.inject.Inject;
    +import javax.inject.Singleton;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.xwiki.component.annotation.Component;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer;
    +import org.xwiki.platform.security.requiredrights.RequiredRightsException;
    +
    +import com.xpn.xwiki.objects.classes.PropertyClass;
    +
    +/**
    + * Required rights analyzer for a {@link PropertyClass}. Analyzes the custom display script.
    + *
    + * @since 15.10.16
    + * @since 16.4.7
    + * @since 16.10.2
    + * @version $Id$
    + */
    +@Component
    +@Singleton
    +public class PropertyClassRequiredRightAnalyzer implements RequiredRightAnalyzer<PropertyClass>
    +{
    +    @Inject
    +    private XClassWikiContentAnalyzer wikiContentAnalyzer;
    +
    +    @Override
    +    public List<RequiredRightAnalysisResult> analyze(PropertyClass propertyClass) throws RequiredRightsException
    +    {
    +        if (propertyClass != null && StringUtils.isNotBlank(propertyClass.getCustomDisplay())) {
    +            return this.wikiContentAnalyzer.analyzeWikiContent(propertyClass.getOwnerDocument().getXClass(),
    +                propertyClass.getCustomDisplay(), propertyClass.getReference());
    +        }
    +
    +        return List.of();
    +    }
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/analyzer/XClassWikiContentAnalyzer.java+91 0 added
    @@ -0,0 +1,91 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.analyzer;
    +
    +import java.util.List;
    +
    +import javax.inject.Inject;
    +import javax.inject.Named;
    +import javax.inject.Singleton;
    +
    +import org.apache.commons.lang3.exception.ExceptionUtils;
    +import org.xwiki.component.annotation.Component;
    +import org.xwiki.model.reference.ClassPropertyReference;
    +import org.xwiki.platform.security.requiredrights.RequiredRight;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer;
    +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider;
    +import org.xwiki.rendering.block.XDOM;
    +import org.xwiki.rendering.parser.ContentParser;
    +
    +import com.xpn.xwiki.objects.classes.BaseClass;
    +
    +/**
    + * Helper component to analyze a wiki content property of an XClass.
    + *
    + * @since 15.10.16
    + * @since 16.4.7
    + * @since 16.10.2
    + * @version $Id$
    + */
    +@Component(roles = XClassWikiContentAnalyzer.class)
    +@Singleton
    +public class XClassWikiContentAnalyzer
    +{
    +    @Inject
    +    private ContentParser contentParser;
    +
    +    @Inject
    +    private RequiredRightAnalyzer<XDOM> xdomRequiredRightAnalyzer;
    +
    +    @Inject
    +    @Named("translation")
    +    private BlockSupplierProvider<String> translationMessageSupplierProvider;
    +
    +    @Inject
    +    @Named("stringCode")
    +    private BlockSupplierProvider<String> stringCodeBlockSupplierProvider;
    +
    +    /**
    +     * Analyze the wiki content in a property of an XClass.
    +     *
    +     * @param xClass the XClass whose property contains the provided wiki content
    +     * @param script the wiki content to analyze
    +     * @param reference the reference of the property containing the wiki content
    +     * @return the analysis result
    +     */
    +    public List<RequiredRightAnalysisResult> analyzeWikiContent(BaseClass xClass, String script,
    +        ClassPropertyReference reference)
    +    {
    +        try {
    +            XDOM scriptXDOM = this.contentParser.parse(script, xClass.getOwnerDocument().getSyntax(),
    +                xClass.getDocumentReference());
    +            scriptXDOM.getMetaData().addMetaData(XDOMRequiredRightAnalyzer.ENTITY_REFERENCE_METADATA, reference);
    +            return this.xdomRequiredRightAnalyzer.analyze(scriptXDOM);
    +        } catch (Exception e) {
    +            return List.of(new RequiredRightAnalysisResult(reference,
    +                this.translationMessageSupplierProvider.get("security.requiredrights.class.errorAnalyzingWiki",
    +                    ExceptionUtils.getRootCauseMessage(e)),
    +                this.stringCodeBlockSupplierProvider.get(script),
    +                List.of(RequiredRight.MAYBE_PROGRAM)));
    +        }
    +    }
    +
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/analyzer/XWikiDocumentRequiredRightAnalyzer.java+7 1 modified
    @@ -41,6 +41,7 @@
     import com.xpn.xwiki.XWikiContext;
     import com.xpn.xwiki.doc.XWikiDocument;
     import com.xpn.xwiki.objects.BaseObject;
    +import com.xpn.xwiki.objects.classes.BaseClass;
     
     /**
      * @version $Id$
    @@ -63,6 +64,9 @@ public class XWikiDocumentRequiredRightAnalyzer implements RequiredRightAnalyzer
         @Inject
         private RequiredRightAnalyzer<BaseObject> objectRequiredRightAnalyzer;
     
    +    @Inject
    +    private RequiredRightAnalyzer<BaseClass> classRequiredRightAnalyzer;
    +
         @Inject
         private VelocityDetector velocityDetector;
     
    @@ -94,13 +98,15 @@ public List<RequiredRightAnalysisResult> analyze(XWikiDocument document) throws
                     // Analyze the content
                     result.addAll(this.xdomRequiredRightAnalyzer.analyze(document.getXDOM()));
     
    -                // Analyze XObjects on the Root locale version of the document
    +                // Analyze XObjects and XClass on the Root locale version of the document
                     XWikiDocument rootLocaleDocument = document;
                     if (document.getLocale() != null && !document.getLocale().equals(Locale.ROOT)) {
                         XWikiContext context = this.contextProvider.get();
                         rootLocaleDocument = context.getWiki().getDocument(document.getDocumentReference(), context);
                     }
     
    +                result.addAll(this.classRequiredRightAnalyzer.analyze(rootLocaleDocument.getXClass()));
    +
                     for (List<BaseObject> baseObjects : rootLocaleDocument.getXObjects().values()) {
                         for (BaseObject object : baseObjects) {
                             result.addAll(this.objectRequiredRightAnalyzer.analyze(object));
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/display/BaseCollectionBlockSupplierProvider.java+18 7 renamed
    @@ -32,27 +32,32 @@
     import org.xwiki.component.annotation.Component;
     import org.xwiki.localization.ContextualLocalizationManager;
     import org.xwiki.localization.Translation;
    +import org.xwiki.model.reference.EntityReference;
     import org.xwiki.rendering.block.Block;
     import org.xwiki.rendering.block.CompositeBlock;
     import org.xwiki.rendering.block.FormatBlock;
     import org.xwiki.rendering.block.GroupBlock;
     import org.xwiki.rendering.listener.Format;
     
     import com.xpn.xwiki.XWikiContext;
    +import com.xpn.xwiki.objects.BaseCollection;
     import com.xpn.xwiki.objects.BaseObject;
     import com.xpn.xwiki.objects.classes.BaseClass;
     import com.xpn.xwiki.objects.classes.PropertyClass;
     import com.xpn.xwiki.objects.classes.TextAreaClass;
     
     /**
    - * Provider for a displayer for an XObject.
    + * Provider for a displayer for an XObject or XClass.
      *
      * @version $Id$
    - * @since 15.9RC1
    + * @since 15.10.16
    + * @since 16.4.7
    + * @since 16.10.2
      */
     @Component
     @Singleton
    -public class XObjectDisplayerProvider extends AbstractBlockSupplierProvider<BaseObject>
    +public class BaseCollectionBlockSupplierProvider
    +    extends AbstractBlockSupplierProvider<BaseCollection<? extends EntityReference>>
     {
         @Inject
         private Provider<XWikiContext> xWikiContextProvider;
    @@ -61,7 +66,7 @@ public class XObjectDisplayerProvider extends AbstractBlockSupplierProvider<Base
         private ContextualLocalizationManager contextualLocalizationManager;
     
         @Override
    -    public Supplier<Block> get(BaseObject object, Object... parameters)
    +    public Supplier<Block> get(BaseCollection<? extends EntityReference> object, Object... parameters)
         {
             // Get and thereby store the values that require a context, so we can be sure we get them in the context of
             // the document that has the object.
    @@ -81,9 +86,15 @@ public Supplier<Block> get(BaseObject object, Object... parameters)
                 })
                 .collect(Collectors.toList());
     
    -        List<PropertyDisplay> deprecatedPropertyNamesValues = xClass.getDeprecatedObjectProperties(object).stream()
    -            .map(p -> new PropertyDisplay(p.getName(), null, p.getValue().toString(), false))
    -            .collect(Collectors.toList());
    +        List<PropertyDisplay> deprecatedPropertyNamesValues;
    +
    +        if (object instanceof BaseObject baseObject) {
    +            deprecatedPropertyNamesValues = xClass.getDeprecatedObjectProperties(baseObject).stream()
    +                .map(p -> new PropertyDisplay(p.getName(), null, p.getValue().toString(), false))
    +                .collect(Collectors.toList());
    +        } else {
    +            deprecatedPropertyNamesValues = List.of();
    +        }
     
             Translation removedPropertiesMessage =
                 this.contextualLocalizationManager.getTranslation("core.editors.object.removeDeprecatedProperties.info");
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/java/org/xwiki/platform/security/requiredrights/internal/display/BaseObjectBlockSupplierProvider.java+53 0 added
    @@ -0,0 +1,53 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.display;
    +
    +import java.util.function.Supplier;
    +
    +import javax.inject.Inject;
    +import javax.inject.Singleton;
    +
    +import org.xwiki.component.annotation.Component;
    +import org.xwiki.model.reference.EntityReference;
    +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider;
    +import org.xwiki.rendering.block.Block;
    +
    +import com.xpn.xwiki.objects.BaseCollection;
    +import com.xpn.xwiki.objects.BaseObject;
    +
    +/**
    + * Block supplier provider for {@link BaseObject}.
    + *
    + * @version $Id$
    + * @since 15.9RC1
    + */
    +@Component
    +@Singleton
    +public class BaseObjectBlockSupplierProvider implements BlockSupplierProvider<BaseObject>
    +{
    +    @Inject
    +    private BlockSupplierProvider<BaseCollection<? extends EntityReference>> baseCollectionBlockSupplierProvider;
    +
    +    @Override
    +    public Supplier<Block> get(BaseObject object, Object... parameters)
    +    {
    +        return this.baseCollectionBlockSupplierProvider.get(object, parameters);
    +    }
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/resources/ApplicationResources.properties+14 0 modified
    @@ -99,6 +99,20 @@ security.requiredrights.object.configurableClassHeading=The heading of the confi
     security.requiredrights.object.pdfClass=The export customization [{0}] contains Velocity code which requires script \
       rights and might use programming rights.
     
    +####################
    +# For XClass
    +####################
    +security.requiredrights.class.errorAnalyzingWiki=Error analyzing the wiki content: [{0}], please manually review the \
    +  content to determine which rights it requires.
    +security.requiredrights.class.dbListVelocity=A database list property with Velocity content requires script right and \
    +  might require programming right.
    +security.requiredrights.class.unsafeNamedQuery=An unsafe named query requires programming right.
    +security.requiredrights.class.unsafeQuery=An unsafe HQL query requires programming right.
    +security.requiredrights.class.errorParsingQuery=Error parsing the HQL query: [{0}], please manually review it to \
    +  determine the rights it requires.
    +security.requiredrights.class.errorAnalyzingProperty=Error analyzing the property: [{0}], please manually review it to \
    +  determine the rights it requires.
    +
     ####################
     # For the edit confirmation checker. 
     ####################
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/main/resources/META-INF/components.txt+7 1 modified
    @@ -1,14 +1,20 @@
     org.xwiki.platform.security.requiredrights.internal.analyzer.XWikiDocumentRequiredRightAnalyzer
    +org.xwiki.platform.security.requiredrights.internal.analyzer.ComputedFieldClassRequiredRightAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.ConfigurableClassRequiredRightsAnalyzer
    +org.xwiki.platform.security.requiredrights.internal.analyzer.DBListClassRequiredRightAnalyzer
    +org.xwiki.platform.security.requiredrights.internal.analyzer.DefaultBaseClassRequiredRightAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.DefaultMacroBlockRequiredRightAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.DefaultMacroRequiredRightReporter
     org.xwiki.platform.security.requiredrights.internal.analyzer.DefaultObjectRequiredRightAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.XDOMRequiredRightAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.PDFClassObjectRequiredRightsAnalyzer
    +org.xwiki.platform.security.requiredrights.internal.analyzer.PropertyClassRequiredRightAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.ScriptMacroAnalyzer
     org.xwiki.platform.security.requiredrights.internal.analyzer.SkinExtensionObjectRequiredRightAnalyzer
    +org.xwiki.platform.security.requiredrights.internal.analyzer.XClassWikiContentAnalyzer
     org.xwiki.platform.security.requiredrights.internal.display.TranslationMessageSupplierProvider
    -org.xwiki.platform.security.requiredrights.internal.display.XObjectDisplayerProvider
    +org.xwiki.platform.security.requiredrights.internal.display.BaseCollectionBlockSupplierProvider
    +org.xwiki.platform.security.requiredrights.internal.display.BaseObjectBlockSupplierProvider
     org.xwiki.platform.security.requiredrights.internal.display.MacroDisplayerProvider
     org.xwiki.platform.security.requiredrights.internal.display.StringCodeBlockSupplierProvider
     org.xwiki.platform.security.requiredrights.internal.configuration.DefaultRequiredRightsConfiguration
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/test/java/org/xwiki/platform/security/requiredrights/internal/analyzer/DefaultBaseClassRequiredRightAnalyzerTest.java+314 0 added
    @@ -0,0 +1,314 @@
    +/*
    + * See the NOTICE file distributed with this work for additional
    + * information regarding copyright ownership.
    + *
    + * This is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU Lesser General Public License as
    + * published by the Free Software Foundation; either version 2.1 of
    + * the License, or (at your option) any later version.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * Lesser General Public License for more details.
    + *
    + * You should have received a copy of the GNU Lesser General Public
    + * License along with this software; if not, write to the Free
    + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    + */
    +package org.xwiki.platform.security.requiredrights.internal.analyzer;
    +
    +import java.util.List;
    +import java.util.Map;
    +
    +import javax.inject.Named;
    +import javax.inject.Provider;
    +
    +import org.junit.jupiter.api.BeforeEach;
    +import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.params.ParameterizedTest;
    +import org.junit.jupiter.params.provider.CsvSource;
    +import org.xwiki.component.manager.ComponentManager;
    +import org.xwiki.model.reference.ClassPropertyReference;
    +import org.xwiki.model.reference.DocumentReference;
    +import org.xwiki.platform.security.requiredrights.RequiredRight;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult;
    +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer;
    +import org.xwiki.platform.security.requiredrights.RequiredRightsException;
    +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider;
    +import org.xwiki.query.Query;
    +import org.xwiki.query.QueryBuilder;
    +import org.xwiki.query.QueryException;
    +import org.xwiki.query.hql.internal.HQLStatementValidator;
    +import org.xwiki.rendering.block.WordBlock;
    +import org.xwiki.rendering.block.XDOM;
    +import org.xwiki.rendering.parser.ContentParser;
    +import org.xwiki.rendering.parser.MissingParserException;
    +import org.xwiki.rendering.parser.ParseException;
    +import org.xwiki.rendering.syntax.Syntax;
    +import org.xwiki.test.annotation.ComponentList;
    +import org.xwiki.test.junit5.mockito.ComponentTest;
    +import org.xwiki.test.junit5.mockito.InjectComponentManager;
    +import org.xwiki.test.junit5.mockito.InjectMockComponents;
    +import org.xwiki.test.junit5.mockito.MockComponent;
    +import org.xwiki.test.mockito.MockitoComponentManager;
    +import org.xwiki.velocity.internal.util.VelocityDetector;
    +
    +import com.xpn.xwiki.doc.XWikiDocument;
    +import com.xpn.xwiki.internal.store.hibernate.HibernateStore;
    +import com.xpn.xwiki.objects.classes.BaseClass;
    +import com.xpn.xwiki.objects.classes.ComputedFieldClass;
    +import com.xpn.xwiki.objects.classes.DBListClass;
    +import com.xpn.xwiki.objects.classes.PropertyClass;
    +
    +import static org.junit.jupiter.api.Assertions.assertEquals;
    +import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.verify;
    +import static org.mockito.Mockito.verifyNoInteractions;
    +import static org.mockito.Mockito.when;
    +
    +/**
    + * Component test for {@link DefaultBaseClassRequiredRightAnalyzer}.
    + *
    + * @version $Id$
    + */
    +@SuppressWarnings("checkstyle:ClassFanOutComplexity")
    +@ComponentTest
    +@ComponentList({
    +    VelocityDetector.class,
    +    ComputedFieldClassRequiredRightAnalyzer.class,
    +    DBListClassRequiredRightAnalyzer.class,
    +    PropertyClassRequiredRightAnalyzer.class,
    +    XClassWikiContentAnalyzer.class
    +})
    +class DefaultBaseClassRequiredRightAnalyzerTest
    +{
    +    protected static final ClassPropertyReference PROPERTY_REFERENCE = mock();
    +
    +    private static final DocumentReference DOCUMENT_REFERENCE = new DocumentReference("wiki", "space", "page");
    +
    +    private static final Syntax SYNTAX = mock();
    +
    +    @InjectMockComponents
    +    private DefaultBaseClassRequiredRightAnalyzer defaultBaseClassRequiredrightAnalyzer;
    +
    +    @MockComponent
    +    private QueryBuilder<DBListClass> dbListClassQueryBuilder;
    +
    +    @MockComponent
    +    private HibernateStore hibernate;
    +
    +    @MockComponent
    +    private ContentParser contentParser;
    +
    +    @MockComponent
    +    private RequiredRightAnalyzer<XDOM> xdomRequiredRightAnalyzer;
    +
    +    @MockComponent
    +    private HQLStatementValidator hqlStatementValidator;
    +
    +    @MockComponent
    +    @Named("stringCode")
    +    private BlockSupplierProvider<String> stringCodeBlockSupplierProvider;
    +
    +    @InjectComponentManager
    +    private MockitoComponentManager componentManager;
    +
    +    @MockComponent
    +    @Named("context")
    +    private Provider<ComponentManager> contextComponentManager;
    +
    +    @BeforeEach
    +    void beforeEach()
    +    {
    +        when(this.contextComponentManager.get()).thenReturn(this.componentManager);
    +    }
    +
    +    @Test
    +    void analyzeWithEmptyCustomDisplay() throws Exception
    +    {
    +        PropertyClass propertyClass = mock();
    +        when(propertyClass.getCustomDisplay()).thenReturn("");
    +
    +        assertWikiContentAnalysis(propertyClass, "", false);
    +    }
    +
    +    @Test
    +    void analyzeWithWikiCustomDisplay() throws Exception
    +    {
    +        String content = "Wiki content.";
    +        PropertyClass propertyClass = mock();
    +        when(propertyClass.getCustomDisplay()).thenReturn(content);
    +
    +        assertWikiContentAnalysis(propertyClass, content, true);
    +    }
    +
    +    @Test
    +    void analyzeEmptyComputedProperty() throws Exception
    +    {
    +        ComputedFieldClass computedFieldClass = mock(ComputedFieldClass.class);
    +        when(computedFieldClass.getScript()).thenReturn("");
    +
    +        assertWikiContentAnalysis(computedFieldClass, "", false);
    +    }
    +
    +    @Test
    +    void analyzeWikiComputedProperty() throws Exception
    +    {
    +        String content = "Computed property.";
    +        ComputedFieldClass computedFieldClass = mock(ComputedFieldClass.class);
    +        when(computedFieldClass.getScript()).thenReturn(content);
    +
    +        assertWikiContentAnalysis(computedFieldClass, content, true);
    +    }
    +
    +    @Test
    +    void analyzeComputedPropertyWhenParsingThrows() throws Exception
    +    {
    +        ComputedFieldClass computedFieldClass = mock(ComputedFieldClass.class);
    +        when(computedFieldClass.getScript()).thenReturn("Script");
    +
    +        when(this.contentParser.parse("Script", SYNTAX, DOCUMENT_REFERENCE))
    +            .thenThrow(new ParseException("Test Exception"));
    +
    +        List<RequiredRightAnalysisResult> results =
    +            this.defaultBaseClassRequiredrightAnalyzer.analyze(mockBaseClass(computedFieldClass));
    +
    +        assertEquals(1, results.size());
    +        RequiredRightAnalysisResult result = results.get(0);
    +        assertEquals(computedFieldClass.getReference(), result.getEntityReference());
    +        assertEquals(List.of(RequiredRight.MAYBE_PROGRAM), result.getRequiredRights());
    +    }
    +
    +    private void assertWikiContentAnalysis(PropertyClass propertyClass, String expectedContent, boolean hasWikiContent)
    +        throws ParseException, MissingParserException, RequiredRightsException
    +    {
    +        BaseClass xClass = mockBaseClass(propertyClass);
    +        XDOM xdom = new XDOM(List.of(new WordBlock("TestContent")));
    +        when(this.contentParser.parse(expectedContent, SYNTAX, DOCUMENT_REFERENCE)).thenReturn(xdom);
    +
    +        RequiredRightAnalysisResult expectedResult = mock();
    +        when(this.xdomRequiredRightAnalyzer.analyze(xdom)).thenReturn(List.of(expectedResult));
    +
    +        List<RequiredRightAnalysisResult> results = this.defaultBaseClassRequiredrightAnalyzer.analyze(xClass);
    +
    +        if (hasWikiContent) {
    +            assertEquals(1, results.size());
    +            RequiredRightAnalysisResult result = results.get(0);
    +            assertEquals(expectedResult, result);
    +            verify(this.contentParser).parse(expectedContent, SYNTAX, DOCUMENT_REFERENCE);
    +            verify(this.xdomRequiredRightAnalyzer).analyze(xdom);
    +            assertEquals(PROPERTY_REFERENCE,
    +                xdom.getMetaData().getMetaData(XDOMRequiredRightAnalyzer.ENTITY_REFERENCE_METADATA));
    +        } else {
    +            verifyNoInteractions(this.contentParser);
    +            verifyNoInteractions(this.xdomRequiredRightAnalyzer);
    +            assertEquals(List.of(), results);
    +        }
    +    }
    +
    +    @ParameterizedTest
    +    @CsvSource({
    +        "select doc.title from XWikiDocument as doc, false, false",
    +        "select doc.fullName from XWikiDocument as doc, false, true",
    +        "#set($x = 1) SELECT * FROM XWikiDocument, true, false",
    +        " , false, true"
    +    })
    +    void analyzeDBListClassSQL(String sql, boolean requiresScript, boolean isSafe) throws Exception
    +    {
    +        DBListClass dbListClass = mock(DBListClass.class);
    +        when(dbListClass.getSql()).thenReturn(sql);
    +        BaseClass xClass = mockBaseClass(dbListClass);
    +
    +        Query query = mock();
    +        when(query.getStatement()).thenReturn(sql);
    +        when(this.dbListClassQueryBuilder.build(dbListClass)).thenReturn(query);
    +
    +        when(this.hqlStatementValidator.isSafe(sql)).thenReturn(isSafe);
    +
    +        List<RequiredRightAnalysisResult> results =
    +            this.defaultBaseClassRequiredrightAnalyzer.analyze(xClass);
    +
    +        if (requiresScript) {
    +            assertEquals(1, results.size());
    +            RequiredRightAnalysisResult result = results.get(0);
    +            assertEquals(PROPERTY_REFERENCE, result.getEntityReference());
    +            assertEquals(RequiredRight.SCRIPT_AND_MAYBE_PROGRAM, result.getRequiredRights());
    +        } else if (isSafe) {
    +            assertEquals(List.of(), results);
    +        } else {
    +            assertEquals(1, results.size());
    +            RequiredRightAnalysisResult result = results.get(0);
    +            assertEquals(dbListClass.getReference(), result.getEntityReference());
    +            assertEquals(List.of(RequiredRight.PROGRAM), result.getRequiredRights());
    +        }
    +    }
    +
    +    @ParameterizedTest
    +    @CsvSource({
    +        "select doc.title from XWikiDocument as doc, false",
    +        "select doc.fullName from XWikiDocument as doc, true",
    +    })
    +    void analyzeDBListClassWithNamedQuery(String hqlQuery, boolean safe) throws Exception
    +    {
    +        DBListClass dbListClass = mock(DBListClass.class);
    +        String queryName = "namedQuery";
    +        when(dbListClass.getSql()).thenReturn(queryName);
    +        Query query = mock();
    +        when(query.isNamed()).thenReturn(true);
    +        when(query.getStatement()).thenReturn(queryName);
    +        when(this.dbListClassQueryBuilder.build(dbListClass)).thenReturn(query);
    +        when(this.hibernate.getConfiguration()).thenReturn(mock());
    +        when(this.hibernate.getConfiguration().getNamedQueries()).thenReturn(Map.of(queryName, mock()));
    +        when(this.hibernate.getConfiguration().getNamedQueries()
    +            .get(queryName).getQuery()).thenReturn(hqlQuery);
    +
    +        when(this.hqlStatementValidator.isSafe(hqlQuery)).thenReturn(safe);
    +
    +        List<RequiredRightAnalysisResult> results =
    +            this.defaultBaseClassRequiredrightAnalyzer.analyze(mockBaseClass(dbListClass));
    +
    +        if (safe) {
    +            assertEquals(List.of(), results);
    +        } else {
    +            assertEquals(1, results.size());
    +            RequiredRightAnalysisResult result = results.get(0);
    +            assertEquals(PROPERTY_REFERENCE, result.getEntityReference());
    +            assertEquals(List.of(RequiredRight.PROGRAM), result.getRequiredRights());
    +        }
    +    }
    +
    +    @Test
    +    void analyzeDBListClassWithQueryException() throws RequiredRightsException, QueryException
    +    {
    +        DBListClass dbListClass = mock(DBListClass.class);
    +        when(dbListClass.getSql()).thenReturn("query");
    +
    +        when(this.dbListClassQueryBuilder.build(dbListClass)).thenThrow(new QueryException("Error parsing query",
    +            mock(), new Exception("Test")));
    +
    +        List<RequiredRightAnalysisResult> results =
    +            this.defaultBaseClassRequiredrightAnalyzer.analyze(mockBaseClass(dbListClass));
    +
    +        assertEquals(1, results.size());
    +        RequiredRightAnalysisResult result = results.get(0);
    +        assertEquals(PROPERTY_REFERENCE, result.getEntityReference());
    +        assertEquals(List.of(RequiredRight.MAYBE_PROGRAM), result.getRequiredRights());
    +    }
    +
    +    private static BaseClass mockBaseClass(PropertyClass propertyClass)
    +    {
    +        when(propertyClass.getReference()).thenReturn(PROPERTY_REFERENCE);
    +        BaseClass xClass = mock();
    +        when(xClass.getDocumentReference()).thenReturn(DOCUMENT_REFERENCE);
    +        when(xClass.getFieldList()).thenReturn(List.of(propertyClass));
    +        XWikiDocument document = mock();
    +        when(document.getDocumentReference()).thenReturn(DOCUMENT_REFERENCE);
    +        when(document.getSyntax()).thenReturn(SYNTAX);
    +        when(document.getXClass()).thenReturn(xClass);
    +        when(xClass.getOwnerDocument()).thenReturn(document);
    +        when(propertyClass.getOwnerDocument()).thenReturn(document);
    +        return xClass;
    +    }
    +}
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/test/java/org/xwiki/platform/security/requiredrights/internal/analyzer/XWikiDocumentRequiredRightAnalyzerTest.java+11 1 modified
    @@ -37,6 +37,7 @@
     
     import com.xpn.xwiki.doc.XWikiDocument;
     import com.xpn.xwiki.objects.BaseObject;
    +import com.xpn.xwiki.objects.classes.BaseClass;
     
     import static org.junit.jupiter.api.Assertions.assertEquals;
     import static org.mockito.ArgumentMatchers.any;
    @@ -63,6 +64,9 @@ class XWikiDocumentRequiredRightAnalyzerTest
         @MockComponent
         private RequiredRightAnalyzer<BaseObject> objectRequiredRightAnalyzer;
     
    +    @MockComponent
    +    private RequiredRightAnalyzer<BaseClass> baseClassRequiredRightAnalyzer;
    +
         @MockComponent
         private VelocityDetector velocityDetector;
     
    @@ -81,6 +85,9 @@ void analyze() throws Exception
             BaseObject object = mock();
             when(document.getXObjects()).thenReturn(Map.of(mock(), List.of(object)));
     
    +        BaseClass baseClass = mock();
    +        when(document.getXClass()).thenReturn(baseClass);
    +
             XDOM xdom = mock();
             when(document.getXDOM()).thenReturn(xdom);
             RequiredRightAnalysisResult xdomResult = mock();
    @@ -89,7 +96,10 @@ void analyze() throws Exception
             RequiredRightAnalysisResult objectResult = mock();
             when(this.objectRequiredRightAnalyzer.analyze(object)).thenReturn(List.of(objectResult));
     
    -        assertEquals(List.of(xdomResult, objectResult), this.analyzer.analyze(document));
    +        RequiredRightAnalysisResult baseClassResult = mock();
    +        when(this.baseClassRequiredRightAnalyzer.analyze(baseClass)).thenReturn(List.of(baseClassResult));
    +
    +        assertEquals(List.of(xdomResult, baseClassResult, objectResult), this.analyzer.analyze(document));
         }
     
         @Test
    
  • xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-requiredrights/xwiki-platform-security-requiredrights-default/src/test/java/org/xwiki/platform/security/requiredrights/internal/display/BaseCollectionBlockSupplierProviderTest.java+3 3 renamed
    @@ -50,7 +50,7 @@
     import static org.mockito.Mockito.when;
     
     /**
    - * Unit tests for {@link XObjectDisplayerProvider}.
    + * Unit tests for {@link BaseCollectionBlockSupplierProvider}.
      * 
      * @version $Id$
      */
    @@ -62,14 +62,14 @@
         PlainTextBlockParser.class,
         PlainTextStreamParser.class
     })
    -class XObjectDisplayerProviderTest
    +class BaseCollectionBlockSupplierProviderTest
     {
         @Inject
         @Named("event/1.0")
         private BlockRenderer eventRenderer;
     
         @InjectMockComponents
    -    private XObjectDisplayerProvider provider;
    +    private BaseCollectionBlockSupplierProvider provider;
     
         @Test
         void getWithNormalProperties()
    

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

5

News mentions

0

No linked articles in our index yet.