CVE-2018-1000088: Stored XSS in Doorkeeper

Software Description

Doorkeeper is a Ruby gem that makes it easy to introduce OAuth 2 provider functionality to a Rails or Grape application.

Depending on how a developer uses the gem, they may allow any registered user to create OAuth client applications in their software.


Base Score: 7.6 (High)
Temporal Score: 6.8 (Medium)

Attack Details

Stored XSS on the OAuth Client's name will cause users being prompted for consent via the "implicit" grant type to execute the XSS payload.

The XSS attack could gain access to the user's active session, resulting in account compromise.

Any user is susceptible if they click the authorization link for the malicious OAuth client. Because of how the links work, a user cannot tell if a link is malicious or not without first visiting the page with the XSS payload.

The requirement for this attack to be dangerous in the wild is the software using Doorkeeper must allow regular users to create or edit OAuth client applications.

If 3rd parties are allowed to create OAuth clients in the app using Doorkeeper, upgrade to the patched versions immediately.

Additionally there is stored XSS in the native_redirect_uri form element.

DWF has assigned CVE-2018-1000088.

Proof of Concept

See Doorkeeper issue #970:

  1. Log in as a user capable of creating OAuth client applications
  2. Create an OAuth client application
  3. Set the Client Name to <script>alert('XSS')</script>
  4. Trick other users to click your implicit authorization link


  1. Discovered by Gauthier Monserand May 25, 2017
  2. Fix prepared by Gauthier Monserand May 25, 2017
  3. Maintainer released patched version May 26, 2017
  4. CVE requested February 17, 2018
  5. CVE assigned February 20, 2018
  6. This post is published February 21, 2018

Affected Versions

v2.1.0 – v4.2.5


Not Using Custom Views

If the software using Doorkeeper did not generate custom views, simply upgrade to v4.2.6 or greater.

Using Custom Views

Any software using Doorkeeper with custom views must manually escape the fields:

In app/views/doorkeeper/authorizations/new.html.erb:

Look for the raw field for client_name and ensure no explicit HTML exists in the value. Use Rails' safe helpers if HTML is required (such as content_tag). e.g. this diff

-    <%= raw t('.prompt', client_name: "<strong class=\"text-info\">#{ }</strong>") %>
+    <%= raw t('.prompt', client_name: content_tag(:strong, class: 'text-info') { }) %>

In app/views/doorkeeper/applications/_form.html.erb:

Look for the raw field for native_redirect_uri and ensure no explicit HTML exists in the value. Use Rails' safe helpers if HTML is required (such as content_tag). e.g. this diff

-  <%= raw t('', native_redirect_uri: "{gfm-js-extract-pre-1}") %>
+  <%= raw t('', native_redirect_uri: content_tag(:code) { Doorkeeper.configuration.native_redirect_uri }) %>

Credit & References

Discovered and fixed by Gauthier Monserand: