Allow iframe embeds in markdown from allowed src domains

What does this MR do and why?

  • Adds admin settings to (a) enable iframe embeds in Markdown, and (b) manage the allowlist of iframe src domains.
  • Uses those settings to transform recognised embeds into live iframes on the frontend.

This MR builds on (and is comprised of!) @digitalmoksha's and @clavimoniere's hard work to to give GitLab the power to safely include user-specified embeds in Markdown fields.

!204952 (merged) added the preliminary filter which recognises image tags ![](url) from domains known to contain embeddable, non-image content, the same way we currently do for directly-embedded video URLs, like ![](https://some-url.com/some-video.mp4). These image tags are annotated with a class which the frontend then picks up, the same way we do for other complex media types such as Mermaid diagrams.

This MR adds the application settings to enable this behaviour, and configure which domains are permitted. These settings are used in three places:

  • When CSP is enabled on a GitLab instance, the nominated domains are added to the frame-src CSP directive. This ensures browsers do not block the iframes when added by the frontend.
  • The backend uses the allowlist to recognise and annotate which image tags should be considered by the frontend.
  • The frontend searches for these annotations, and refers to the allowlist to then turn those elements into live iframes.

The repetition of work between the backend and frontend is crucial: the backend's recognition and annotation is cached as part of the Markdown render. If an administrator removes an item from the allowlist (or disables Markdown embeds entirely), this will take effect immediately without needing to invalidate the Markdown cache or modify affected content, as the frontend will refuse to construct iframes for domains no longer permitted, and won't do anything with them at all if the feature is disabled entirely, leaving broken image tags — the status quo.

These settings, while easy to configure, are nonetheless complex: correctly choosing the domain list may take some nuance, and I think we'll want to apply some documentation to make it easier for our instance administrators to choose working values. See !200864 (comment 2865240554) for a breakdown using YouTube and Figma as examples.

References

Screenshots or screen recordings

Enabling embedding and configuring the allowlist:

image

Using the image/video embed syntax to embed a YouTube video:

image

The result:

image

Using the image/video embed syntax to embed a Figma design:

image

The result:

image

Steps to reproduce

  1. Check out the branch on your local GDK.

  2. From a Rails console, enable the allow_iframes_in_markdown feature flag. (Optionally, enable it for a specific group or project.)

    [13] pry(main)> Feature.enable(:allow_iframes_in_markdown)
    
    ... lots of output ...
    
    WARNING: Understand the stability and security risks of enabling in-development features with feature flags.
    See https://docs.gitlab.com/ee/administration/feature_flags.html#risks-when-enabling-features-still-in-development for more information.
    => true
  3. Navigate to Admin → Settings → General → Iframe embedding, enable "Allow iframes in Markdown", and enter domains to enable. www.youtube.com is a good start. Make sure you save changes.

    image

  4. Navigate to a Markdown area and enter an embeddable URL in the format ![](url) in the plaintext editor. (If you enabled the feature flag for a specific group or project, make sure you're within it.) For example, in creating an issue:

    image

  5. View the created item.

    image

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Asherah Connor

Merge request reports

Loading