Tl;dr

oEmbed automatically lowercases scheme urls making it impossible to use schemes that should have capital letters in them. It also makes it impossible to accept any urls with capital letters in them (when these capital letters are part of the scheme).

Description

Drupal relies on https://oembed.com/providers.json to indicate the possible schemes for streaming video urls from various services. Vimeo has the scheme "https:\/\/player.vimeo.com\/video\/*" etc. You can also implement your own oEmbed providers.json.

The bug is that the oEmbed Endpoint class lowercases the schemes automatically, but compares them against a non-lowercased user input with a case sensitive regex. This means that any capital letters in the scheme will cause the regex to fail, making it impossible to create your own scheme that has capital letters.

I discovered the bug while creating a custom oEmbed provider for Panopto (academia video streaming service). The scheme looks like this:

"https:\/\/demo.hosted.panopto.com\/Panopto\/Pages\/Viewer.aspx*"

As you can see, there are uppercase words in the url scheme and lowercasing the scheme automatically and then comparing it case sensitively to a Panopto supplied video url will always fail.

The offending code is in Drupal\media\OEmbed\Endpoint.php on line #72 (array map of schemes to mb_strtolower) and in the method matchUrl (line #155) where the case sensitive regex is made.

Steps to reproduce

Unfortunately this is a chore to reproduce, since there are currently no official oembed schemes with capital letters.

- You need to implement your own @MediaSource class that extends OEmbed.
- You also need to implement your own oEmbed providers.json and configure a provider (such as Panopto) with a variable case scheme.
- You also need to override media.settings for your custom oEmbed providers.json so Drupal reads it instead of the canonical one.
- Don't forget to clear your cache to load the new oEmbed providers.
- Now add your own media type (structure / media types / add) using the MediaSource class you just implemented.
- In the case of Panopto, which doesn't have its own oEmbed endpoint, we have to simulate / implement one ourselves in Drupal.
- Now try to add a Panopto video using the example above. It will never be accepted, because Drupal lowercases your scheme and compares it against your Panopto url with capital letters in it.

Expected behavior

I expect the media entity to be accepted when its url matches my oEmbed provider scheme even if the scheme has capital letters in it.

What happened instead

The media is rejected with the error message "The provided URL does not represent a valid oEmbed resource.".

Proposed solution

I can think of two easy ways:

- Change the regex to be case insensitive in Endpoint.php #155 OR
- Remove the lowercasing of schemes in Endpoint.php #72

At first glance, the latter seems the more appropriate one. We should not lowercase schemes if there is a chance a valid url (such as in the case of Panopto) has capital letters in it.

Issue fork drupal-3054888

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

jcalais created an issue. See original summary.

jcalais’s picture

Issue summary: View changes
jcalais’s picture

StatusFileSize
new666 bytes

Just a quick patch that removes the lowercasing of schemes.

cilefen’s picture

Status: Active » Needs review

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

jay.dansand’s picture

Version: 8.9.x-dev » 9.1.x-dev

+1 for RTBC. I just found this issue as I was about to submit my own similar patch. It still applies cleanly as of Drupal 9.1.5, so I'm bumping the issue's Drupal version to the now-active version. Thanks for your work!

Adding my 2 cents for the pro-patch argument: There's no logical reason to force endpoint URIs (the things site builders can actually control) to be lower-cased before comparing against the user's input (the thing we cannot control). If anything, assume the user may error when entering the URI (an argument for a case-insensitive match), not the other way around.

Either we want a case-insensitive comparison or a strict match, and the current method accomplishes neither while breaking endpoints with mixed-case URIs (the problem I just hit up against). Maintaining the current strict (but currently broken) match seems the least invasive step, so let's go for it!

chris matthews’s picture

Version: 9.1.x-dev » 9.3.x-dev
Assigned: jcalais » Unassigned
Issue tags: -media, -oembed
phenaproxima’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

🤔 Yeah, I'm not sure why we lowercased the schemes in the Endpoint constructor. I wish we'd put a comment there to explain the reasoning. Since we don't have that, I'm okay with removing the mb_strtolower() call.

This is going to need an automated test in any event; I think we could easily do this by adding a simple unit test for Endpoint (a test class already exists at https://git.drupalcode.org/project/drupal/-/blob/9.3.x/core/modules/medi..., so we could modify that).

phenaproxima’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new794 bytes

Wrote a test. Here's a fail patch to prove it catches the bug. I'm pushing that, plus the fix in #3, to the merge request.

phenaproxima’s picture

Title: Oembed does not handle mixed case url schemes » oEmbed endpoints should not lowercase the available schemes

Re-titling for clarity.

Status: Needs review » Needs work

The last submitted patch, 10: 3054888-10-FAIL.patch, failed testing. View results

phenaproxima’s picture

Status: Needs work » Needs review

Fail patch failed as expected.

lendude’s picture

Will removing mb_strtolower() give a BC break if sites currently depend on this happening?

phenaproxima’s picture

Will removing mb_strtolower() give a BC break if sites currently depend on this happening?

Reasons I'm not worried about BC in this case:

  • There is no clear reason why we are lowercasing the schemes to begin with.
  • The only providers core supports out of the box are YouTube and Vimeo. According to https://oembed.com/providers.json, both of them already have completely lowercase schemes, so existing sites which are using core's YouTube and Vimeo implementations should be unaffected by this bug.
  • That URL is the default provider list used by Drupal. I didn't do an exhaustive search or anything, but I'm not seeing any providers with mixed-case schemes (including the more popular ones like Facebook, SoundButt, Instagram, and Twitter). So I doubt that this would be encountered under normal circumstances. You'd need a custom provider with a mixed-case scheme.
  • And if you were trying to use a custom provider with a mixed-case scheme, you'd run into this bug and it wouldn't have worked anyway. (As the issue summary points out.)

Right now in HEAD, if someone tried to match a mixed-case URL (httpS://TWiTTer.com/OembeD/... or some other goofy thing) against a legitimate lowercased endpoint, it would fail anyway since the regex is case-sensitive.

So thank you for asking that question, @Lendude. 🙏 Maybe I'm missing something, but I don't really see any realistic BC break here.

lendude’s picture

Status: Needs review » Reviewed & tested by the community

@phenaproxima excellent, in that case this looks ready to me.

catch’s picture

Status: Reviewed & tested by the community » Fixed

If we wanted to restrict to lowercase I think we'd want to add validation somewhere, since we don't have that seems fine to remove the normalisation.

Leaving this as 9.3.x-only though, just in case we have missed something.

  • catch committed 114e523 on 9.3.x
    Issue #3054888 by phenaproxima, jcalais, Lendude, jay.dansand: oEmbed...

Status: Fixed » Closed (fixed)

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