Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refused to frame 'https://www.youtube.com/' because it violates the following Content Security Policy directive #42

Closed
distributeddev opened this issue Nov 1, 2022 · 10 comments

Comments

@distributeddev
Copy link

distributeddev commented Nov 1, 2022

I am getting following error in browser console and I cant see the preview in the editor when embedding videos

Refused to frame 'https://www.youtube.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.

main.95e79f29.js:15982 Refused to frame 'https://player.vimeo.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.

main.95e79f29.js:15982 Refused to frame 'https://www.youtube.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.

main.95e79f29.js:15982 Refused to frame 'https://player.vimeo.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.

And this is what I see in browser

Screenshot 2022-11-01 at 14 53 16

Following is my middlware.js in strapi.

module.exports = [
  "strapi::errors",
  {
    name: "strapi::security",
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          "connect-src": ["'self'", "https:"],
          "default-src": [
            "'self'",
            "data:",
            "blob:",
            "res.cloudinary.com",
            "lh3.googleusercontent.com",
            "platform-lookaside.fbsbx.com",
            "dl.airtable.com",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],          
          "img-src": [
            "'self'",
            "data:",
            "blob:",
            "res.cloudinary.com",
            "lh3.googleusercontent.com",
            "platform-lookaside.fbsbx.com",
            "dl.airtable.com",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],
          "media-src": [
            "'self'",
            "data:",
            "blob:",
            "res.cloudinary.com",
            "lh3.googleusercontent.com",
            "platform-lookaside.fbsbx.com",
            "dl.airtable.com",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],
          "frame-src": [
            "'self'",
            "data:",
            "blob:",
            "res.cloudinary.com",
            "lh3.googleusercontent.com",
            "platform-lookaside.fbsbx.com",
            "dl.airtable.com",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],
          "iframe-src": [
            "'self'",
            "data:",
            "blob:",
            "res.cloudinary.com",
            "lh3.googleusercontent.com",
            "platform-lookaside.fbsbx.com",
            "dl.airtable.com",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],          
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  "strapi::security",
  "strapi::cors",
  "strapi::poweredBy",
  {
    name: "strapi::cors",
    config: {
      enabled: true,
      headers: "*",
      origin: ["*"],
    },
  },
  "strapi::logger",
  "strapi::query",
  "strapi::body",
  "strapi::session",
  "strapi::favicon",
  "strapi::public",
];

any idea?

@dannyrippon
Copy link

@distributeddev it looks like you have strapi::security twice. Just remove the second one above "strapi::cors"

@denvradiy
Copy link

I faced the same issue, did you find out how to fix this ?

@denvradiy
Copy link

denvradiy commented Nov 9, 2022

Hi @distributeddev !

Here is my middlewares.js

module.exports = [
  'strapi::errors',
  'strapi::poweredBy',
  'strapi::logger',
  'strapi::query',
  'strapi::body',
  'strapi::session',
  'strapi::favicon',
  'strapi::public',

  {
    name: "strapi::security",
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          "connect-src": ["'self'", "https:"],
          "default-src": [
            "'self'",
            "data:",
            "blob:",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],
          "img-src": [
            "'self'",
            "data:",
            "blob:",
            "s3.eu-west-1.amazonaws.com",
          ],
          "media-src": [
            "'self'",
            "data:",
            "blob:",
            "s3.eu-west-1.amazonaws.com",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],
          "frame-src": [
            "'self'",
            "data:",
            "blob:",
            "https://www.youtube.com/",
            "https://www.youtube.com/embed/",
            "https://player.vimeo.com/",
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  {
    name: 'strapi::cors',
    config: {
      enabled: true,
      headers: '*',
      origin: ['*'],
    }
  }
];

It fixed the issue for me, try it!

@oDinZu
Copy link

oDinZu commented Dec 3, 2022

Awesome, this also worked for me! You rock and thank you for sharing. I was digging into my nginx CSP, but it looks like Strapi also has its own CSP.

Update: If you are using nginx security CSP, you will also need to add *.youtube.com *.vimeo.com etc... to your CSP, plus doing the above.

Update 2: This link provides more data on how these embeds are displayed and which ones are allowed. We may need to add to this config for other social providers.

 Media providers

CKEditor 5 comes with several supported media providers that can be extended or altered.

Names of providers with previews:

    'dailymotion',
    'spotify',
    'youtube',
    'vimeo'.

Names of providers without previews:

    'instagram',
    'twitter',
    'googleMaps',
    'flickr',
    'facebook'.

https://ckeditor.com/docs/ckeditor5/latest/features/media-embed.html#media-providers

Update 3:

Yeah, for spotify I had to add it to both nginx and strapi.

"*.spotify.com",
"*.dailymotion.com"

to frame-src allowed spotify and dailymotion embed to populate.

@oDinZu
Copy link

oDinZu commented Dec 4, 2022

Also important to note, this plugin allows for PREVIEWING the embeded content, but the ` html attribute must be converted into proper HTML for the item to be displayed.

😓

This plugin is useless unless you either:

  1. Pay embedly or iframely money
  2. Program your own syntax to convert attributes into an <iframe> template formatting.

the HTML syntax used.

<figure class="media"><oembed url="https://www.youtube.com/watch?v=bX_Ihr0"></oembed></figure>

For an example of 2., the actual code the <oembed> needs to be converted into from youtube.

<iframe width="560" height="315" src="https://www.youtube.com/embed/DvkQo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

@timraasveld
Copy link
Contributor

timraasveld commented Dec 20, 2022

EDIT: This answer is only for strapi-plugin-ckeditor 1.x.x, not for 2.x.x

Also important to note, this plugin allows for PREVIEWING the embeded content, but the ` html attribute must be converted into proper HTML for the item to be displayed.

😓

This plugin is useless unless you either:

  1. Pay embedly or iframely money
  2. Program your own syntax to convert attributes into an <iframe> template formatting.

the HTML syntax used.

<figure class="media"><oembed url="https://www.youtube.com/watch?v=bX_Ihr0"></oembed></figure>

For an example of 2., the actual code the <oembed> needs to be converted into from youtube.

<iframe width="560" height="315" src="https://www.youtube.com/embed/DvkQo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

To make the MediaEmbed plugin output an iframe that you can insert directly in your client app, add previewsInData: true in plugins.ts/.js:

ckeditor: {
  config: {
    ..
    editor: {
      ...
      mediaEmbed: {
        previewsInData: true

This results in the following HTML when pasting a YT video:

<figure class="media">
    <div data-oembed-url="https://www.youtube.com/watch?v=TcbFFoAQ5Ck">
        <div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 56.2493%;">
            <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen=""></iframe>
        </div>
    </div>
</figure>

Alternatively, to have full control over the output, define your own markup by overriding the mediaEmbed providers, just copy-paste the default YT provider in your providers list:

mediaEmbed: {
  providers: [
    				{
					name: 'youtube',
					url: [
						/^(?:m\.)?youtube\.com\/watch\?v=([\w-]+)(?:&t=(\d+))?/,
						/^(?:m\.)?youtube\.com\/v\/([\w-]+)(?:\?t=(\d+))?/,
						/^youtube\.com\/embed\/([\w-]+)(?:\?start=(\d+))?/,
						/^youtu\.be\/([\w-]+)(?:\?t=(\d+))?/
					],
					html: match => {
						const id = match[ 1 ];
						const time = match[ 2 ];

						return YOUR_HTML
                   			}
				},

  ]
}

@oDinZu
Copy link

oDinZu commented Dec 23, 2022

Sweet, I will give this a test the next time I get the chance.

@dinhkhanh
Copy link

dinhkhanh commented Mar 29, 2023

I've added previewsInData: true but it still produces "semantic" data.

My /config/plugins.ts:

ckeditor5: {
    enabled: true,
    config: {
      editor: {
        mediaEmbed: {
          previewsInData: true
        }
      }
   }
},

Using "@_sh/strapi-plugin-ckeditor": "^2.0.4", version.

What did I do wrong? I've also try /config/ckeditor.ts and /config/ckeditor.txt but still doesn't work.

@timraasveld
Copy link
Contributor

I've added previewsInData: true but it still produces "semantic" data.

My /config/plugins.ts:

ckeditor5: {
    enabled: true,
    config: {
      editor: {
        mediaEmbed: {
          previewsInData: true
        }
      }
   }
},

Using "@_sh/strapi-plugin-ckeditor": "^2.0.4", version.

What did I do wrong? I've also try /config/ckeditor.ts and /config/ckeditor.txt but still doesn't work.

The answer I showed is for CKEditor 1.x.x. In 2.x.x, it seems you can only use /config/ckeditor.txt, which I have no experience with. I might be able to figure it out later when I have time to upgrade to 2.x.

@dinhkhanh
Copy link

I've added previewsInData: true but it still produces "semantic" data.

My /config/plugins.ts:

ckeditor5: {

enabled: true,
config: {
  editor: {
    mediaEmbed: {
      previewsInData: true
    }
  }

}

},

Using "@_sh/strapi-plugin-ckeditor": "^2.0.4", version.

What did I do wrong? I've also try /config/ckeditor.ts and /config/ckeditor.txt but still doesn't work.

The answer I showed is for CKEditor 1.x.x. In 2.x.x, it seems you can only use /config/ckeditor.txt, which I have no experience with. I might be able to figure it out later when I have time to upgrade to 2.x.

Found out that an typo error in the code base causes my issue, as I describe here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants