Skip to content

Vite 8 regression: cross-origin classic script request to /src/*.ts returns 403 #21849

Closed

Description

@Denis6902

Describe the bug

Vite 8 dev server returns 403 Forbidden for cross-origin classic script requests to /src/*.ts files, while the same setup works in Vite 7.3 and in rolldown-vite.

This was reproduced with a minimal setup using only the vanilla-ts template.

Reproduction setup:

  • Project A: plain Vite vanilla-ts app
  • Project B: plain Vite vanilla-ts app
  • Project A loads a source file from Project B using a classic script tag:
<script src="http://localhost:5174/src/counter.ts"></script>

Observed behavior:

  • If Project B uses vite@7.3.x, the script loads correctly
  • If Project B uses vite@8.x, the request returns 403 Forbidden
  • If Project B uses rolldown-vite, it also works correctly

Additional notes:

  • The failure only happens when the file is loaded via <script src="..."> from a different origin. Directly opening the same URL in the browser works.
  • This does not appear to be a Rolldown issue, because the same reproduction works with rolldown-vite.

Reproduction

https://github.com/Denis6902/vite8-cross-origin-script-403-repro

Steps to reproduce

  1. Create two separate Vite projects using the vanilla-ts template
  2. Run Project A on one port, for example 5173
  3. Run Project B on another port, for example 5174
  4. In Project A, add this to index.html:
<script src="http://localhost:5174/src/counter.ts"></script>
  1. Start both dev servers
  2. Open Project A in the browser

System Info

System:
    OS: Windows 11 10.0.26200
    CPU: (16) x64 Intel(R) Core(TM) i5-14400
    Memory: 9.91 GB / 31.77 GB
  Binaries:
    Node: 22.22.0 - C:\nvm4w\nodejs\node.EXE
    npm: 10.9.4 - C:\nvm4w\nodejs\npm.CMD
  Browsers:
    Chrome: 145.0.7632.160
    Edge: Chromium (145.0.3800.58)
  npmPackages:
    vite: ^8.0.0 => 8.0.0

Used Package Manager

npm

Logs

No response

Validations

Activity

  1. added theissue type on Mar 13, 2026
  2. added a commit that references this issue on Mar 14, 2026
    8654057
  3. sapphi-red commented on Mar 16, 2026

    @sapphi-red
    Member

    Since Vite serves ESM files referencing files with a script tag without type="module" does not make sense to me.

  4. Denis6902 commented on Mar 16, 2026

    @Denis6902
    Author

    This is a somewhat unusual setup, so here is the context.

    I’m using Vite with Blazor WASM via backend integration. In practice, Vite is used for SCSS and normal ESM TypeScript modules.

    The exception is my custom TinyMCE plugins. TinyMCE external_plugins expects a URL to a plugin entry file that TinyMCE loads itself at startup, rather than an ESM import handled by my app/bundler.

    So this is not me trying to use /src/*.ts as a public asset endpoint in a generic way, but rather a result of integrating custom TinyMCE plugins in a Blazor setup where the other integration options I tried did not work for me.

    The reason I reported it is that the same setup worked on Vite 7.3.x, but returns 403 Forbidden on Vite 8, while opening the same URL directly still works.

    So I understand this may not be a primary Vite use case, but from my side the Vite 7 -> 8 behavior change made it look regression-like, which is why I reported it.

    If this is not a supported use case in Vite 8, I’d be happy to know that explicitly so I can look for a different integration strategy.

  5. added a commit that references this issue on Mar 17, 2026
    381873b
  6. sapphi-red commented on Mar 17, 2026

    @sapphi-red
    Member

    I guess you should be able to solve this by setting crossorigin option.
    https://www.tiny.cloud/docs/tinymce/latest/tinymce-and-cors/#crossorigin

    tinymce.init({
      selector: "textarea",
      crossorigin: () => "anonymous"
    });
  7. Denis6902 commented on Mar 17, 2026

    @Denis6902
    Author

    Thanks, crossorigin solved the original 403 on my side.

    In my case, because I am using the TinyMCE Blazor wrapper, I could not pass this through the normal C# Conf object since TinyMCE expects a JavaScript callback there. The working solution was to use JsConfSrc and define:

    crossorigin: () => 'anonymous'

    That fixed the cross-origin loading problem for my TinyMCE plugin entry.

    After that, I ran into a separate issue where a plugin entry containing top-level import type ends up with export {}; in the served output, which then breaks because TinyMCE loads it as a classic script.

    That second issue does not happen for me with regular Vite 7.3.1. I can reproduce it with Vite 8 and with rolldown-vite, so it seems to be a separate topic rather than part of this original 403 regression.

    So from my side, the original 403 is resolved by using crossorigin via JsConfSrc.

  8. locked and limited conversation to collaborators on May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions