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

[WebViews] Support Content Security Policy that has "vscode-resource" entry #11982

Closed
marcdumais-work opened this issue Dec 12, 2022 · 0 comments · Fixed by #12070
Closed

[WebViews] Support Content Security Policy that has "vscode-resource" entry #11982

marcdumais-work opened this issue Dec 12, 2022 · 0 comments · Fixed by #12070
Assignees
Labels
preview issues related to the preview vscode issues related to VSCode compatibility webviews issues related to webviews

Comments

@marcdumais-work
Copy link
Contributor

marcdumais-work commented Dec 12, 2022

Bug Description:

In webviews contributed by extensions, it's possible for them to set a Content Security Policy (CSP) that helps protect against cross-origin resource sharing (CORS) exploits. Microsoft's Markdown Preview contribution and others do that, with several levels of configurable CSP "levels", from "strict" to "disable":
image

At the moment, some webview contributions can't display locally-stored images (and potentially other resources) without using a lower-security CSP level. If level "strict" is used, the images will not load and a warning like this will be in the browser console:

Refused to load the image 'http://fdd8cdf0-ce21-443a-b44f-e101721b1a49.webview.localhost:34741/webview…/project/files/img/image1.png' because it violates the following Content Security Policy directive: "img-src vscode-resource: https: data:".

The same preview in vscode works, using "strict" CSP.

After investigation, it was found that using "vscode-resource" as part of CSP is the old way of doing things. In recent vscode, vscode-resource is now replaced on-the-fly by

'self' https://*.vscode-cdn.net

I think we may want to leave-out the later part, but we can use 'self', which basically means same origin:

When you encounter the self keyword in a Content-Security-Policy header directive it is an alias for the same origin. The same origin includes the scheme (http:// or https://) as well as the domain name.

This issue was found by investigating a bug report about the preview contributed by extension asciidoctor:
eclipse-theia/theia-ide#244

Here is its strict CSP:

    case AsciidocPreviewSecurityLevel.Strict:
    default:
      return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https: data:; media-src vscode-resource: https: data:; script-src 'nonce-${nonce}'; style-src vscode-resource: 'unsafe-inline' https: data:; font-src vscode-resource: https: data:;">`;
    }

I have confirmed that if we use 'self` instead of vscode-resource, images load correctly.

Note: there's already code in Theia that seems to attempt to do this, but it fails doing it correctly. As far as I can see, data.endpoint is never defined, and so the replacement never takes place.

Steps to Reproduce:

  1. Build and start the Theia Electron example from sources. Developing.md
  2. Install extension asciidoctor from extensions view
  3. open an asciidoc source file that references local images. E.g. "article.adoc" from repo asciidoc-samples
  4. open the preview for the source file (click the corresponding button at the top right corner of editor)
  5. confirm that images are not shown in preview
  6. look into the dev-tools console to see that a CORS violation has occurred, preventing images being loaded.

Additional Information

Suggested fix:

file: packages/plugin-ext/src/main/browser/webview/pre/main.js
line: starts ~384

note: the substitution is copied directly from vscode sources and slightly adapted to Theia. The Theia file we're modifying here is already documented as being a fork of the corresponding vscode file (see header), so that's ok.

const sameOrigin = '\'self\'';  // see: https://content-security-policy.com/self/
// Check for CSP
const csp = newDocument.querySelector('meta[http-equiv="Content-Security-Policy"]');
if (csp !== null) {
    const cspContent = csp.getAttribute('content');
    if (cspContent !== null) {
        // Rewrite vscode-resource in csp
        try {
            csp.setAttribute('content', cspContent.replace(/(vscode-webview-resource|vscode-resource):(?=(\s|;|$))/g, sameOrigin));
        } catch (e) {
            console.error('Could not rewrite csp');
        }
    }
} else {
    host.postMessage('no-csp-found');
}

In diff form:

+            const sameOrigin = '\'self\'';  // see: https://content-security-policy.com/self/
             // Check for CSP
             const csp = newDocument.querySelector('meta[http-equiv="Content-Security-Policy"]');
-            if (!csp) {
-                host.postMessage('no-csp-found');
-            } else {
-                // Rewrite vscode-resource in csp
-                if (data.endpoint) {
+            if (csp !== null) {
+                const cspContent = csp.getAttribute('content');
+                if (cspContent !== null) {
+                    // Rewrite vscode-resource in csp
                     try {
-                        const endpointUrl = new URL(data.endpoint);
-                        csp.setAttribute('content', csp.getAttribute('content').replace(/(?:vscode|theia)-resource:(?=(\s|;|$))/g, endpointUrl.origin));
+                        csp.setAttribute('content', cspContent.replace(/(vscode-webview-resource|vscode-resource):(?=(\s|;|$))/g, sameOrigin));
                     } catch (e) {
                         console.error('Could not rewrite csp');
                     }
                 }
+            } else {
+                host.postMessage('no-csp-found');
             }
@marcdumais-work marcdumais-work added preview issues related to the preview webviews issues related to webviews labels Dec 12, 2022
@marcdumais-work marcdumais-work self-assigned this Dec 12, 2022
@marcdumais-work marcdumais-work added hackathon issues reserved for hackatons vscode issues related to VSCode compatibility and removed hackathon issues reserved for hackatons labels Dec 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
preview issues related to the preview vscode issues related to VSCode compatibility webviews issues related to webviews
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant