PDF viewer fails when app:// PDF URL is cross-origin under Electron 39.8.10+ CORS enforcement

Steps to reproduce

  1. Run Obsidian 1.12.7 with system Electron 39.8.10 or newer Electron containing the custom-protocol CORS enforcement from Electron commit 5392e9a9ad.
  2. Open a vault containing any known-good PDF.
  3. Open the PDF in Obsidian’s built-in PDF viewer.
  4. Open the developer console and check the PDF loading errors.

Downgrading only Electron to 39.8.9 makes the same PDF render correctly again.

Did you follow the troubleshooting guide? [Y/N]

Y

Expected result

The PDF should render normally in Obsidian’s built-in PDF viewer.

Actual result

The PDF viewer stays blank.

The developer console shows a CORS failure while PDF.js tries to load the PDF from an app:// URL:

Access to XMLHttpRequest at 'app://<vault-or-file-host>/path/to/file.pdf?...'
from origin 'app://obsidian.md'
has been blocked by CORS policy:
Cross origin requests are only supported for protocol schemes:
chrome, chrome-extension, chrome-untrusted, data, http, https.

Failed to load resource: net::ERR_FAILED

pdf.pdfjs-unexpected-response-error

PDF.js v5.3.34
Message: Unexpected server response (0) while retrieving PDF "app://<vault-or-file-host>/path/to/file.pdf?...".

The important detail is that the viewer page origin is:

app://obsidian.md

but the PDF is requested from a different app:// origin:

app://<hash-or-other-host>/path/to/file.pdf

So PDF.js appears to be making a cross-origin XHR/fetch request to a custom Electron protocol URL.

Environment

Known affected environment:

Operating system: Linux
Obsidian version: 1.12.7
Electron package: electron39 39.8.10

Known working downgrade:

obsidian 1.12.7
electron39 39.8.9

Additional information

I compared Electron v39.8.9 and v39.8.10.

The relevant Electron 39 commit appears to be:

5392e9a9ad fix: ensure corsEnabled: false protocol handlers do not work across protocols (39-x-y)

This was backported from Electron main commit:

92f0993d94 fix: ensure corsEnabled: false protocol handlers do not work across protocols

That change adds CORS enforcement in Electron’s custom protocol loader. Before this change, renderer-initiated cross-origin XHR/fetch requests to custom Electron protocols could reach the protocol handler even when the scheme was not registered with corsEnabled: true.

After this change, Electron blocks such requests before the protocol handler is invoked.

This matches the Obsidian PDF failure:

  1. PDF.js loads PDFs using XHR/fetch-style requests.
  2. Obsidian’s viewer is loaded from app://obsidian.md.
  3. The PDF file is loaded from another app:// host/origin.
  4. Electron 39.8.10+ blocks the cross-origin request because the custom app scheme does not appear to be CORS-enabled.
  5. PDF.js reports Unexpected server response (0).

Likely app-side fixes would be one of:

  1. Register the app protocol with corsEnabled: true before app.ready, for example via Electron’s protocol.registerSchemesAsPrivileged.

    Conceptually:

    protocol.registerSchemesAsPrivileged([
      {
        scheme: 'app',
        privileges: {
          standard: true,
          secure: true,
          supportFetchAPI: true,
          corsEnabled: true
        }
      }
    ])
    
  2. Or avoid loading PDFs from a different app:// origin than the viewer page.

Related existing Arch-focused thread:

Thanks for the more detailed report. You are experiencing this problem because you are using a package we do not make.
I thought I was clear about this in the thread you linked.

When we upgrade to a newer version of electron, we will deal with this.

Will be fixed once we release the next public builds with the latest Electron.

1 Like