CVE-2023-29016 (Other, published 2023-04-06T20:15Z)
Description: value: The Goobi viewer is a web application that allows digitised material to be displayed in a web browser. A cross-site scripting vulnerability has been identified in Goobi viewer core prior to version 23.03 when using nicknames. An attacker could create a user account and enter malicious scripts into their profile's nickname, resulting in the execution in the user's browser when displaying the nickname on certain pages. The vulnerability has been fixed in version 23.03.
Severity: nan (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/intranda/goobi-viewer-core
Files changed:
goobi-viewer-core/src/main/java/io/goobi/viewer/faces/validators/NameValidator.java
goobi-viewer-core/src/main/resources/META-INF/resources/resources/admin/views/adminDashboard.xhtml
goobi-viewer-core/src/main/resources/META-INF/resources/resources/admin/views/adminUsers.xhtml
goobi-viewer-core/src/main/resources/META-INF/resources/resources/tags/user/userData.xhtml
goobi-viewer-core/src/test/java/io/goobi/viewer/faces/validators/NameValidatorTest.java
Commit message: added nickname validator; html escape existing values when displaying;
refs #24571

Vulnerable code:
	                                    <h2>#{msg.admin__dashboard_hello} #{userBean.user.nickName}</h2>
                                        <span class="admin__table-name">#{user.nickName}</span>
									requiredMessage="#{msg.loginEnterDisplayName}" />

Fixed code:
/*
 * This file is part of the Goobi viewer - a content presentation and management
 * application for digitized objects.
 *
 * Visit these websites for more information.
 *          - http://www.intranda.com
 *          - http://digiverso.com
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package io.goobi.viewer.faces.validators;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import io.goobi.viewer.messages.ViewerResourceBundle;

/**
 * Syntax validator for names (e.g. nickname).
 */
@FacesValidator("nameValidator")
public class NameValidator implements Validator<String> {

    private static final String REGEX =  "^[\\w ]+$"; //NOSONAR   input size is limited
    private static final Pattern PATTERN = Pattern.compile(REGEX);

    /* (non-Javadoc)
     * @see javax.faces.validator.Validator#validate(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
     */
    /** {@inheritDoc} */
    @Override
    public void validate(FacesContext context, UIComponent component, String value) throws ValidatorException {
        if (!validate(value)) {
            FacesMessage msg = new FacesMessage(ViewerResourceBundle.getTranslation("pi_errInvalid", null), "");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(msg);
        }
    }

    /**
     * <p>
     * validateEmailAddress.
     * </p>
     *
     * @param email a {@link java.lang.String} object.
     * @should match correct name
     * @should not match invalid name
     * @return a boolean.
     */
    public static boolean validate(String name) {
        if (name == null || name.length() > 10_000) {
            return false;
        }
        Matcher m = PATTERN.matcher(name.toLowerCase());
        return m.find();
    }
}
	                                    <h2>#{msg.admin__dashboard_hello} <h:outputText value="#{userBean.user.nickName}" escape="true" /></h2>
                                        <span class="admin__table-name"><h:outputText value="#{user.nickName}" escape="true" /></span>
									requiredMessage="#{msg.loginEnterDisplayName}"
									validator="nameValidator" />
/*
 * This file is part of the Goobi viewer - a content presentation and management
 * application for digitized objects.
 *
 * Visit these websites for more information.
 *          - http://www.intranda.com
 *          - http://digiverso.com
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package io.goobi.viewer.faces.validators;

import org.junit.Assert;
import org.junit.Test;

public class NameValidatorTest {

    /**
     * @see NameValidator#validate(String)
     * @verifies match correct name
     */
    @Test
    public void validate_shouldMatchCorrectName() throws Exception {
        Assert.assertTrue(NameValidator.validate("John Doe"));
    }

    /**
     * @see NameValidator#validate(String)
     * @verifies not match invalid name
     */
    @Test
    public void validate_shouldNotMatchInvalidName() throws Exception {
        Assert.assertTrue(NameValidator.validate("John Doe<script />"));
    }
}