CVE-2021-21376 (Python, published 2021-03-23T16:15Z)
Description: value: OMERO.web is open source Django-based software for managing microscopy imaging. OMERO.web before version 5.9.0 loads various information about the current user such as their id, name and the groups they are in, and these are available on the main webclient pages. This represents an information exposure vulnerability. Some additional information being loaded is not used by the webclient and is being removed in this release. This is fixed in version 5.9.0.
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-200 \u2014 Exposure of Sensitive Information to an Unauthorized Actor
The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
Repository: https://github.com/ome/omero-web
Files changed:
CHANGELOG.md
omeroweb/decorators.py
omeroweb/settings.py
omeroweb/webclient/decorators.py
omeroweb/webclient/forms.py
omeroweb/webclient/static/webclient/javascript/ome.tree.js
omeroweb/webclient/templates/webclient/base/base_container.html
omeroweb/webclient/templates/webclient/base/includes/toolbar_forms.html
omeroweb/webclient/templates/webclient/data/containers.html
omeroweb/webclient/templates/webclient/public/public.html
omeroweb/webclient/views.py
omeroweb/webgateway/templates/webgateway/core_html.html
omeroweb/webgateway/views.py
Commit message: SV commits


Vulnerable code:
        pass
from omeroweb.webgateway.marshal import eventContextMarshal
        context["ome"]["eventContext"] = eventContextMarshal(conn.getEventContext())
from omeroweb.webadmin.custom_forms import GroupModelMultipleChoiceField
class BasketShareForm(ShareForm):
    def __init__(self, *args, **kwargs):
        super(BasketShareForm, self).__init__(*args, **kwargs)

        try:
            self.fields["image"] = GroupModelMultipleChoiceField(
                queryset=kwargs["initial"]["images"],
                initial=kwargs["initial"]["selected"],
                widget=forms.SelectMultiple(attrs={"size": 10}),
            )
        except Exception:
            self.fields["image"] = GroupModelMultipleChoiceField(
                queryset=kwargs["initial"]["images"],
                widget=forms.SelectMultiple(attrs={"size": 10}),
            )


                    memberOfGroup = WEBCLIENT.eventContext.memberOfGroups.indexOf(WEBCLIENT.active_group_id) > -1,
                    writeOwned = WEBCLIENT.eventContext.adminPrivileges.indexOf("WriteOwned") > -1,
        WEBCLIENT.eventContext = {{ ome.eventContext|json_dumps|safe }};
  Copyright (C) 2011 University of Dundee & Open Microscopy Environment.

        var productListQuery = [];

        // we do inst.get_selected() here, since we then get objects
        // instead of ids for some reason?
        var inst = $.jstree.reference('#dataTree');
        data = inst.get_selected(true);
        data.forEach(function(node){
            productListQuery.push(node.type + "=" + node.data.id);
        });

        var query = '{% url 'manage_action_containers' "add" "share" %}' + "?"+productListQuery.join("&");
        $("#create_share_form").attr("action", query)
        $("#create_share_form").load(query);
        // AJAX handling of create-discussion form
        $("#create_share_form").ajaxForm({
            success: function(html) {
                if (html.indexOf("shareId") > -1) {
                    var shareId = html.replace("shareId:", "");
                    $("#create_share_form").dialog( "close" );
                    $("#shareCreatedId").text(shareId);
                    $("#share_dialog_form").dialog("open").show();
                } else {
                    $("#create_share_form").html(html);
                }
            },
        });

        $("#share_dialog_form").dialog({
            autoOpen: false,
            resizable: true,
            height: 150,
            width:300,
            modal: true,
            buttons: {
                "OK": function() {
                    $( this ).dialog( "close" );
                }
            }
        });

            height: 600,
                "Accept": function() {
                    // simply submit the form
                    $("#create_share_form").submit();
                },
                "Cancel": function() {



<!-- hidden form for creating share - shown in dialog & loaded by AJAX -->
<form id="create_share_form" action="#" method="post" title="Create Share" class="standard_form">{% csrf_token %}
</form>

<form id="share_dialog_form" action="#" title="Create Share" style="display:none">
    <p style="font-size: 120%; font-weight: bold">
        Share <span id="shareCreatedId"></span> was created successfully.
</form>
            var writeOwned = WEBCLIENT.eventContext.adminPrivileges.indexOf("WriteOwned") > -1;
            var memberOfGroup = WEBCLIENT.eventContext.memberOfGroups.indexOf(WEBCLIENT.active_group_id) > -1;
                memberOfGroup = WEBCLIENT.eventContext.memberOfGroups.indexOf(WEBCLIENT.active_group_id) > -1,
                writeOwned = WEBCLIENT.eventContext.adminPrivileges.indexOf("WriteOwned") > -1,
    <div id="tree_details" class="left_panel_tree">
from .forms import ShareForm, BasketShareForm
    elif action == "add":
        template = "webclient/public/share_form.html"
        experimenters = list(conn.getExperimenters())
        experimenters.sort(key=lambda x: x.getOmeName().lower())
        if o_type == "share":
            img_ids = request.GET.getlist("image", request.POST.getlist("image"))
            if request.method == "GET" and len(img_ids) == 0:
                return HttpResponse("No images specified")
            images_to_share = list(conn.getObjects("Image", img_ids))
            if request.method == "POST":
                form = BasketShareForm(
                    initial={"experimenters": experimenters, "images": images_to_share},
                    data=request.POST.copy(),
                )
                if form.is_valid():
                    images = form.cleaned_data["image"]
                    message = form.cleaned_data["message"]
                    expiration = form.cleaned_data["expiration"]
                    members = form.cleaned_data["members"]
                    # guests = request.POST['guests']
                    enable = form.cleaned_data["enable"]
                    host = "%s?server=%i" % (
                        request.build_absolute_uri(
                            reverse("load_template", args=["public"])
                        ),
                        int(conn.server_id),
                    )
                    shareId = manager.createShare(
                        host, images, message, members, enable, expiration
                    )
                    return HttpResponse("shareId:%s" % shareId)
            else:
                initial = {
                    "experimenters": experimenters,
                    "images": images_to_share,
                    "enable": True,
                    "selected": request.GET.getlist("image"),
                }
                form = BasketShareForm(initial=initial)
        template = "webclient/public/share_form.html"
        context = {"manager": manager, "form": form}
                else None
        range_size = kwargs.get("limit", rows)

Fixed code:
- Security vulnerability fixes for
  [2021-SV1](https://www.openmicroscopy.org/security/advisories/2021-SV1-user-context/),
  [2021-SV2](https://www.openmicroscopy.org/security/advisories/2021-SV2-url-validation/)

        context["html"] = context.get("html", {})
        context["html"]["meta_referrer"] = settings.HTML_META_REFERRER
    "omero.web.session_cookie_path": [
        "SESSION_COOKIE_PATH",
        None,
        leave_none_unset,
        "The path to use for session cookies",
    ],
    "omero.web.redirect_allowed_hosts": [
        "REDIRECT_ALLOWED_HOSTS",
        "[]",
        json.loads,
        (
            "If you wish to allow redirects to an external site, "
            "the domains must be listed here. "
            'For example ["openmicroscopy.org"].'
        ),
    ],
    "omero.web.html_meta_referrer": [
        "HTML_META_REFERRER",
        "origin-when-crossorigin",
        str,
        (
            "Default content for the HTML Meta referrer tag. "
            "See https://www.w3.org/TR/referrer-policy/#referrer-policies for "
            "allowed values and https://caniuse.com/#feat=referrer-policy for "
            "browser compatibility. "
            "Warning: Internet Explorer 11 does not support the default value "
            'of this setting, you may want to change this to "origin" after '
            "reviewing the linked documentation."
        ),
    ],
        super(render_response, self).prepare_context(request, context, *args, **kwargs)

                    memberOfGroup = WEBCLIENT.member_of_groups.indexOf(WEBCLIENT.active_group_id) > -1,
                    writeOwned = WEBCLIENT.current_admin_privileges.indexOf("WriteOwned") > -1,
        WEBCLIENT.member_of_groups = {{ member_of_groups|json_dumps|safe }};
  Copyright (C) 2011-2021 University of Dundee & Open Microscopy Environment.
            title: "Shares not supported",
            height: 250,
                "OK": function() {
<!-- hidden dialog -->
<div id="create_share_form" style="display:none">
    <p>Share functionality is no longer supported.</p>
    <p>Please see <a target="_blank" href="https://www.openmicroscopy.org/omero/features/share/">Sharing your data in OMERO</a>
        for alternative workflows.
</div>
            var writeOwned = WEBCLIENT.current_admin_privileges.indexOf("WriteOwned") > -1;
            var memberOfGroup = WEBCLIENT.member_of_groups.indexOf(WEBCLIENT.active_group_id) > -1;
                memberOfGroup = WEBCLIENT.member_of_groups.indexOf(WEBCLIENT.active_group_id) > -1,
                writeOwned = WEBCLIENT.current_admin_privileges.indexOf("WriteOwned") > -1,
    <div style="height: 110px; padding: 15px; box-sizing: border-box;">
        <p>Creating new shares is no longer supported. Previously created shares are shown below.</p>
        <p>Please see <a target="_blank" href="https://www.openmicroscopy.org/omero/features/share/">Sharing your data in
                OMERO</a>
            for alternative workflows.
        </p>
    </div>

    <div id="tree_details" class="left_panel_tree" style="height: calc(100% - 110px)">
from django.utils.http import is_safe_url
from .forms import ShareForm
def validate_redirect_url(url):
    """
    Returns a URL is safe to redirect to.
    If url is a different host, not in settings.REDIRECT_ALLOWED_HOSTS
    we return webclient index URL.
    """
    if not is_safe_url(url, allowed_hosts=settings.REDIRECT_ALLOWED_HOSTS):
        url = reverse("webindex")
    return url


        else:
            url = validate_redirect_url(url)
    url = validate_redirect_url(url)
    context["member_of_groups"] = conn.getEventContext().memberOfGroups
    <meta name="referrer" content="{{ html.meta_referrer|default:"origin-when-crossorigin" }}">
                else rows
        range_size = limit