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

[bug] fetch and XHR response has no content-range header #11371

Closed
chrox opened this issue Oct 15, 2024 · 7 comments · Fixed by #11374
Closed

[bug] fetch and XHR response has no content-range header #11371

chrox opened this issue Oct 15, 2024 · 7 comments · Fixed by #11374
Labels
status: needs triage This issue needs to triage, applied to new issues type: bug

Comments

@chrox
Copy link
Contributor

chrox commented Oct 15, 2024

Describe the bug

I don't know if it is intended or not but in both asset protocol and the http protocol the content-range header is discarded in fetch response. Without the content-range header successive range requests cannot be performed such as in pdf.js.

This is a normal fetch in macOS Safari browser:
image

And this is a fetch in Tauri app in macOS:
image

The static HTTP server http://localhost:9000 is started with http-server -p 9000 -d . --cors for testing purpose.


And the asset protocol is also affected in Tauri app.

image

Note that in the network inspector the content-range header is present but it's like being discarded somewhere in the fetch response.

image


I also try to figure out where the response headers are intercepted. At least the wry layer hold the intact headers:

[2024-10-15][14:44:11][wry::wkwebview::class::url_scheme_handler][INFO] wry::custom_protocol::handle; uri="asset://localhost/%2FUsers%2Fchrox%2FDocuments%2FReadest%2FBooks%2F3ec18259cf5e8a916a553f14ebf4f7d3%2Fl11manual_zh.pdf"
[2024-10-15][14:44:11][tracing::span][INFO] wry::custom_protocol::call_handler;
response headers: {
    "content-type": "application/pdf",
    "content-range": "bytes 0-65535/91848117",
    "accept-ranges": "bytes",
    "application/pdf": "content-type",
    "content-length": "65536",
    "65536": "content-length",
    "access-control-allow-origin": "http://localhost:3000",
}

Let's set aside for now these two malformed headers "65536": "content-length" and "application/pdf": "content-type" that were introduced by recent code refactoring of wry; the wry url_scheme_handler writes the correct content-range header. I tried to add Access-Control-Allow-Headers: * or Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Range in tauri/src/protocol/asset.ts but it makes no difference on the response headers of fetch and XHR. I have no clue on how the response headers are sent to the Javascript world. Could someone give a hint?

Reproduction

No response

Expected behavior

No response

Full tauri info output

> tauri "info"


[✔] Environment
    - OS: Mac OS 14.3.1 arm64 (X64)
    ✔ Xcode Command Line Tools: installed
    ✔ rustc: 1.81.0 (eeb90cda1 2024-09-04)
    ✔ cargo: 1.81.0 (2dbb1af80 2024-08-20)
    ✔ rustup: 1.27.1 (54dd3d00f 2024-04-24)
    ✔ Rust toolchain: stable-aarch64-apple-darwin (default)
    - node: 22.9.0
    - pnpm: 9.12.1
    - yarn: 1.22.22
    - npm: 10.8.3

[-] Packages
    - tauri 🦀: 2.0.3
    - tauri-build 🦀: 2.0.1
    - wry 🦀: 0.46.1
    - tao 🦀: 0.30.3
    - @tauri-apps/api : 2.0.2
    - @tauri-apps/cli : 2.0.3

[-] Plugins
    - tauri-plugin-http 🦀: 2.0.1
    - @tauri-apps/plugin-http : 2.0.0
    - tauri-plugin-os 🦀: 2.0.1
    - @tauri-apps/plugin-os : 2.0.0
    - tauri-plugin-fs 🦀: 2.0.1
    - @tauri-apps/plugin-fs : 2.0.0
    - tauri-plugin-log 🦀: 2.0.1
    - @tauri-apps/plugin-log : 2.0.0
    - tauri-plugin-dialog 🦀: 2.0.1
    - @tauri-apps/plugin-dialog : 2.0.0

[-] App
    - build-type: bundle
    - CSP: style-src 'self' 'unsafe-inline' blob: asset: http://asset.localhost; default-src 'self' 'unsafe-inline' blob: customprotocol: asset: http://asset.localhost ipc: http://ipc.localhost; frame-src 'self' blob: asset: http://asset.localhost; img-src 'self' blob: data: asset: http://asset.localhost
    - frontendDist: ../out
    - devUrl: http://localhost:3000/
    - framework: React (Next.js)
    - bundler: Webpack

Stack trace

No response

Additional context

No response

@chrox chrox added status: needs triage This issue needs to triage, applied to new issues type: bug labels Oct 15, 2024
@chrox
Copy link
Contributor Author

chrox commented Oct 15, 2024

This is my app.security in tauri.conf.json:

    "security": {
      "csp": {
        "default-src": "'self' 'unsafe-inline' blob: customprotocol: asset: http://asset.localhost ipc: http://ipc.localhost",
        "img-src": "'self' blob: data: asset: http://asset.localhost",
        "style-src": "'self' 'unsafe-inline' blob: asset: http://asset.localhost",
        "frame-src": "'self' blob: asset: http://asset.localhost"
      },
      "assetProtocol": {
        "enable": true,
        "scope": {
          "allow": ["$RESOURCE/**", "$DOCUMENT/**/*", "$APPDATA/**/*", "$TEMP/**/*"],
          "deny": []
        }
      }
    }

And this is the capability config:

 {
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "enables the default permissions",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "fs:default",
    {
      "identifier": "fs:scope-document-recursive",
      "allow": [
        {
          "path": "$DOCUMENT/**/*"
        }
      ],
      "deny": []
    },
    {
      "identifier": "fs:scope-appdata-recursive",
      "allow": [
        {
          "path": "$APPDATA/Readest/**/*"
        }
      ],
      "deny": []
    },
    {
      "identifier": "fs:allow-appdata-read",
      "allow": [
        {
          "path": "$APPDATA/settings.json"
        }
      ]
    },
    {
      "identifier": "fs:allow-appdata-write",
      "allow": [
        {
          "path": "$APPDATA/settings.json"
        }
      ]
    },
    "dialog:default",
    "os:default",
    "http:default"
  ]
}

@chrox
Copy link
Contributor Author

chrox commented Oct 15, 2024

This might be related to #10426.

@chrox
Copy link
Contributor Author

chrox commented Oct 15, 2024

UPDATE:
Adding a access-control-expose-headers: content-range solves this problem.
image

If there is no security concern about this I will send a PR later after more testing.

@amrbashir
Copy link
Member

@chrox feel free to open a PR and @tweidinger will take a look from security prespective.

@amrbashir
Copy link
Member

Let's set aside for now these two malformed headers "65536": "content-length" and "application/pdf": "content-type" that were introduced by recent code refactoring of wry;

Could you open an issue or better a PR if you have a fix?

@chrox
Copy link
Contributor Author

chrox commented Oct 15, 2024

Sure.

@chrox
Copy link
Contributor Author

chrox commented Oct 15, 2024

According to MDN on Access-Control-Expose-Headers, content-range is not a simple response header and not exposed to client scripts by default in CORS response except that it's listed in the Access-Control-Expose-Headers header. The first example I provided above however is not a CORS request thus not affected.

It sounds pretty safe to expose the content-range header in a range request in the asset protocol. I'm opening a PR to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs triage This issue needs to triage, applied to new issues type: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants