The "conditional_fields" module, as verified in version
4.0.0-alpha2, is susceptible to stored cross-site-scripting
exploitable by authenticated attackers with the permissions to create new
conditional fields.

The module lets users configure a customizable JQuery selector for control
fields, but because this field does not perform input validation or output
sanitization, malicious XSS payloads may be persisted and used to attack other
users within the system.

The following steps can be taken to reproduce this issue:

  1. Install Drupal 10.0.3
  2. Install and enable the vulnerable module: composer require 'drupal/conditional_fields:^4.0@alpha'
  3. Navigate to /admin/structure/conditional_fields/node/page
  4. Configure a new conditional field:
    • Target field: Title (title)
    • Controlled by: Body (body)
    • The target field is: Visible
    • when the control field: is Focused
  5. Confirm the new conditional field by click the Add dependency button.
  6. Open the Advanced edit context settings section and configure a "Custom JQuery selector for control field", set the value to: <img src=x onerror=alert('xss')>
  7. Navigate to /node/add/page to trigger the XSS payload
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

cydave created an issue. See original summary.

liquidcms’s picture

Priority: Critical » Minor

I have never understood (critical) security threats defined for an action that only the site administrator would be able to do. Or do you suspect there is some situation where access to configure CFs would be given to non administrators?

greggles’s picture

Version: 4.0.0-alpha2 » 4.x-dev
Priority: Minor » Critical

Thanks for the issue report, @cydave.

Thanks for your thoughts and the question, @liquidcms.

I believe the "Critical" priority and "Security" issue tag are used by the Drupal.org packaging system to help ensure issues that affect security are fixed prior to creating a 4.0.0 final release (at which point valid security issues need to be fixed with a security advisory for projects that are opted in to that process). I don't mean to play "issue priority ping-pong" or discredit your ability to set priority as a module maintainer, but given the special meaning in packaging it seems important to leave the status as the default even if in your evaluation it is not "Critical."

What is the name of the permission that allows someone to create a conditional field? And does it include the "restrict access" flag set to TRUE in the yml?

There are different levels of "administration" permissions, some of them inherently let you take over a site (e.g. administer users) but many of them do not.

I certainly agree that issues that can only be exploited by "admins" with lower levels of permissions/trust are not as important as issues that could be exploited by an anonymous user. However, a cross-site-scripting vulnerability like that does still represent a weakness in a site allowing either a compromised account or a rogue admin to escalate their privileges.

joelpittet’s picture

Linking to the stable release #2830988: [meta] 4.0.0 release roadmap meta

benstallings made their first commit to this issue’s fork.

benstallings’s picture

Status: Active » Needs review

joelpittet’s picture

@greggles, belatedly answering #3: the "Custom jQuery selector" field is on the dependency edit form and is gated by edit conditional fields. None of the module's permissions were marked restrict access: true. The MR now marks that permission as restricted, with a description noting that it can change entity-form behaviour site-wide.

Why that matters even if the permission is normally admin-only: its label sounds like form-display configuration, but before this fix it effectively allowed JavaScript to run in the browser of anyone editing affected content, including more privileged administrators. That creates a privilege-escalation path for a role deliberately denied permissions such as administer users. The payload is also persistent in configuration, surviving cache clears and config export/import.

That seems like exactly what restrict access is for: permissions whose effective power is broader than their name suggests.

joelpittet’s picture

Status: Needs review » Fixed

Fixing this issue before I release a stable. Thanks for bringing this to our attention @cydave

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.