Roundup CVE

This is a list of remediation for CVE’s that are not fixed in the latest release. When the latest release fixes the CVE, see the upgrading doc for these details.

Note

Releases of Roundup from 2.0.0 to 2.5.0 do not check for cross site request forgeries (CSRF) when using the PATCH method. Release 2.6 fixes this issue. If you are running 2.6.0 you don’t have to do anything.

Remediating missing PATCH CSRF protections

If you are using the REST API, there are two ways to fix this issue with releases 2.0.0 through 2.5.0:

  1. if you are not using PATCH in your workflow, disable the PATCH method in your tracker,

  2. patch the cgi/client.py file to include the PATCH method in csrf protections.

Disable PATCH

To disable the PATCH method for your tracker add the following code to the file interfaces.py in your tracker’s home directory:

from roundup.cgi.client import UsageError
from roundup.cgi.client import Client

original_handle_csrf = Client.handle_csrf

def csrf_wrapper_deny_patch(self, api=False):
    method = self.env['REQUEST_METHOD']
    if method == 'PATCH':
        raise UsageError("Blocked Request: %s" % method)
    return original_handle_csrf(self, api)

Client.handle_csrf = csrf_wrapper_deny_patch

then restart your tracker. You can test it using:

curl -u user:password -X PATCH \
    -H "Origin: <origin>" <origin>/rest/data/issue/1

and you should receive:

{ "error": { "status": 400, "msg": "Blocked Request: PATCH"}}

This will disable the use of PATCH in all web requests. When you upgrade to release 2.6, remember to re-enable PATCH you can re-enable it by deleting the code above from interfaces.py.

Apply CSRF Protections

However, if you need to use PATCH request, you can change the installed Roundup source and apply CSRF protections to the PATCH command.

Make a backup copy of the file before changing it. Find the lines in cgi/client.py that look like:

# Assume: never allow changes via GET
if method not in ['POST', 'PUT', 'DELETE']:
    if (self.form.list is not None) and ("@csrf" in self.form):

Change the middle line so it looks like:

if method not in ['POST', 'PUT', 'DELETE', 'PATCH']:

Note

If you are running versions 1.6.0 to version 2.5 the filtering of history/journal items does not work correctly if the property is protected by a check function. Release 2.6.0 fixes this. If you are running 2.6.0, you don’t have to do anything.

Remediating incomplete property permission check

To fix this, you need to find the View and Edit checks in the history method in the roundup/hyperdb.py file. Make a backup copy of the file before making a change. (Note that the 1.6 releases only checked for View permissions.) In the 1.6 release it looks something like:

if enforceperm and not perm("View",
        self.db.getuid(),
        self.classname,
        property=k ):
logger.debug("skipping unViewable property %s in >
             k, j_repr)
del j[4][k]
continue

Add:

itemid=nodeid

to the View (and Edit check if present) so it looks like:

if enforceperm and not perm("View",
        self.db.getuid(),
        self.classname,
        itemid=nodeid,
        property=k )

In the 2.5 and newer releases this code block includes a check for Edit permissions and when fixed looks like:

if enforceperm and not (perm("View",
                             uid,
                             self.classname,
                             itemid=nodeid,
                             property=key) or
                        perm("Edit",
                             uid,
                             self.classname,
                             itemid=nodeid,
                             property=key)):
    logger.debug("skipping unaccessible property "
                 "%s::%s seen by user%s in %s",
                 self.classname, key, uid, j_repr)
    del args[key]
    continue