npm / vite / 8.3.5

vite 8.3.5

Source
https://github.com/vitejs/vite
Tag scanned
v8.3.5
Directory
packages/vite (only this part of the repository was scanned)
Compared with
v8.3.4 (1 signals introduced since)
Files
503 scanned, 60 skipped (binary, oversized, or unrecognised)
Signals
1 critical · 0 warn · 33 info
Scan time
16.8 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 25 of 25 warn and critical signals; 24 demoted to info.
Disclude version
4.1.0
Scanned (UTC)
2026-10-22 15:48

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. critical dynamic-execution packages/vite/src/node/utils.ts:1765:14

    `Function(...)` called with a non-literal body (ast pass, confidence 0.90)

    export function evalValue<T = any>(rawValue: string): T {
      const fn = new Function(`
        var console, exports, global, module, process, require
        return (\n${rawValue}\n)
    suspicious LLM, confidence 0.80 Evaluates a raw string as a JavaScript expression via Function constructor.
    Reasoning

    evalValue builds a Function body around a raw string, a pattern that is dangerous if fed untrusted input. In Vite it is used to parse config values from trusted source such as config files, with a sandboxed set of shadowed globals. It is an intentional, known utility rather than hidden obfuscation, but the evaluation of a string remains a real risk worth a human check of call sites.

  2. info warn → info by review dynamic-import packages/vite/src/client/client.ts:160:27 new in this release

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        const browserUrl = moduleUrlToBrowserUrl(moduleUrl, base)
        const importPromise = import(/* @vite-ignore */ browserUrl)
        if (isWithinCircularImport) {
          importPromise.catch(() => {
    likely benign LLM, confidence 0.87 Vite client dynamically imports a computed module URL.
    Reasoning

    Dynamic import of a browser URL derived from module URL and base for circular-import handling in the Vite client. Expected module-loading behavior with @vite-ignore.

  3. info warn → info by review unicode-mixed-script packages/vite/README.md:12:46

    identifier `viːt` mixes scripts: Latin + Other (raw pass, confidence 0.80)

    
    Vite (French word for "quick", pronounced [`/viːt/`]https://cdn.jsdelivr.net/gh/vitejs/vite@main/docs/public/vite.mp3, like "veet") is a build tool that aims to provide a faster and leaner development experience for modern web projects. It consists of two major parts:
    likely benign LLM, confidence 0.93 IPA pronunciation notation in the Vite README.
    Reasoning

    The mixed-script flag is on IPA phonetic characters (ː) in a pronunciation guide in a README. Legitimate linguistic notation, not an identifier used for evasion.

  4. info warn → info by review dynamic-import packages/vite/src/client/bundledDevHmrClient.ts:345:13

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        try {
          await import(/* @vite-ignore */ this.options.base + url)
        } catch {
          this.requestFullReload(`failed to import hmr patch ${url}`)
    likely benign LLM, confidence 0.85 HMR client dynamically imports a patch module by URL.
    Reasoning

    Dynamic import of an HMR patch URL built from the configured base path. The @vite-ignore comment marks an intentional bundler-skipped import; this is standard Vite HMR behavior, though it loads runtime-determined code from the dev server.

  5. info warn → info by review dynamic-import packages/vite/src/module-runner/esmEvaluator.ts:50:12

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

      runExternalModule(filepath: string): Promise<any> {
        return import(filepath)
      }
    }
    likely benign LLM, confidence 0.85 Module runner evaluator imports an external module by path.
    Reasoning

    The ESM evaluator imports an external module by filepath, which is the purpose of a module runner. The specifier is not attacker-controlled in normal operation, and the AST pattern alone does not show malicious intent.

  6. info warn → info by review dynamic-execution packages/vite/src/module-runner/utils.ts:17:40

    `atob` decodes a base64 value at runtime — common step before dynamic fetch or eval (ast pass, confidence 0.75)

      return (base64: string) =>
        textDecoder.decode(Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)))
    })()
    likely benign LLM, confidence 0.80 Base64 decoding helper using atob and TextDecoder.
    Reasoning

    atob decodes base64 into a TextDecoder for a utility; it is used to decode inline source or sourcemap data, a common and benign pattern. Decoding alone without a subsequent eval sink is not a dropper.

  7. info warn → info by review dynamic-import packages/vite/src/node/__tests__/environment.spec.ts:173:25

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

          const chunk = (output as RolldownOutput).output[0]
          const mod = await import(
            path.join(
              import.meta.dirname,
    likely benign LLM, confidence 0.90 Test imports a built bundle fixture by path.
    Reasoning

    Test file importing a built fixture path via import.meta.dirname. Ordinary test-harness behavior.

  8. file mixes tab and space indentation (16 tab-indented and 638 space-indented lines) (raw pass, confidence 0.40)

    import {
      convertTargets,
      createCSSResolvers,
      cssPlugin,
  9. info warn → info by review dynamic-import packages/vite/src/node/__tests__/resolve.spec.ts:312:24

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        })
        const mod1 = await import(
          join(import.meta.dirname, 'fixtures/file-url/dist/basic/index.js')
        )
    likely benign LLM, confidence 0.92 Test imports a fixture module relative to its directory.
    Reasoning

    Test importing a fixture module via join with import.meta.dirname. Benign test scaffolding.

  10. info warn → info by review dynamic-import packages/vite/src/node/__tests__/resolve.spec.ts:327:24

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        })
        const mod2 = await import(
          join(import.meta.dirname, 'fixtures/file-url/dist/virtual/index.js')
        )
    likely benign LLM, confidence 0.92 Test imports a virtual fixture module.
    Reasoning

    Same pattern as the other resolve test: importing a local fixture file. Benign.

  11. info warn → info by review encoding-base64 packages/vite/src/node/__tests__/utils.spec.ts:45:1

    base64-like blob (1348 bytes over 22 lines, compression ratio 0.71) (raw pass, confidence 0.60)

    -----BEGIN CERTIFICATE-----
    MIID7zCCAtegAwIBAgIJS9D2rIN7tA8mMA0GCSqGSIb3DQEBCwUAMGkxFDASBgNV
    BAMTC2V4YW1wbGUub3JnMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWEx
    EzARBgNVBAcTCkJsYWNrc2J1cmcxDTALBgNVBAoTBFRlc3QxDTALBgNVBAsTBFRl
    likely benign LLM, confidence 0.90 Test fixture containing a PEM certificate.
    Reasoning

    A PEM certificate fixture in a test file. Base64 of a certificate is expected test data, not a payload.

  12. base64-like blob (264 bytes, compression ratio 0.79) (in comment) (raw pass, confidence 0.36)

    https://evanw.github.io/source-map-visualization/#MzQALyogY29tbWVudCAqLwpjb25zb2xlLmxvZygiZm9vIik7CjE1NgB7InZlcnNpb24iOjMsInNvdXJjZXMiOlsiL3NyYy9mb28uanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJmb29cIik7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQzsifQo=
  13. base64-like blob (388 bytes, compression ratio 0.76) (in comment) (raw pass, confidence 0.36)

    https://evanw.github.io/source-map-visualization/#NjMALy8gYi5qcwpjb25zb2xlLmxvZygiLi9iLmpzIik7CgovLyBhLmpzCmNvbnNvbGUubG9nKCIuL2EuanMiKTsKMjIwAHsKICAidmVyc2lvbiI6IDMsCiAgInNvdXJjZXMiOiBbImIuanMiLCAiYS5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiY29uc29sZS5sb2coJy4vYi5qcycpXG4iLCAiaW1wb3J0ICcuL2IuanMnXG5jb25zb2xlLmxvZygnLi9hLm
  14. base64-like blob (440 bytes, compression ratio 0.73) (in comment) (raw pass, confidence 0.36)

    https://evanw.github.io/source-map-visualization/#NjYALmZvbyB7CiAgb3ZlcmZsb3c6IHNjcm9sbDsKICAtd2Via2l0LW92ZXJmbG93LXNjcm9sbGluZzogdG91Y2g7Cn0KMjU1AHsKICAiZmlsZSI6ICIvc3JjL3Nhc3Mvc3R5bGUuc2FzcyIsCiAgIm1hcHBpbmdzIjogIkFBQUE7RUFDRSxnQkFBZ0I7RUNEbEIsa0NBQUE7QURFQSIsCiAgIm5hbWVzIjogW10sCiAgInNvdXJjZXMiOiBbCiAgICAiL3NyYy9zYX
  15. base64-like blob (324 bytes, compression ratio 0.77) (in comment) (raw pass, confidence 0.36)

    https://evanw.github.io/source-map-visualization/#MjkALmZvbyB7CiAgb3ZlcmZsb3c6IHNjcm9sbDsKfQoyMDcAewogICJmaWxlIjogIi9zcmMvc2Fzcy9zdHlsZS5zYXNzIiwKICAibWFwcGluZ3MiOiAiQUFBQTtFQUNFIiwKICAibmFtZXMiOiBbXSwKICAic291cmNlcyI6IFsKICAgICIvc3JjL3Nhc3MvdmVuZG9yL2luZGV4LnNjc3MiCiAgXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi5mb28ge1xuICBvdm
  16. info warn → info by review dynamic-import packages/vite/src/node/config.ts:2483:24

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.80)

    
      const module = await import(
        pathToFileURL(resolvedPath).href + '?t=' + Date.now()
      )
    likely benign LLM, confidence 0.85 Loads the user's Vite config file via dynamic import.
    Reasoning

    Config loader imports a user config file via file URL with a cache-busting query. This is the standard bundled-config loading mechanism in Vite.

  17. info warn → info by review dynamic-import packages/vite/src/node/config.ts:2784:21

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        try {
          return (await import(pathToFileURL(tempFileName).href)).default
        } finally {
          fs.unlink(tempFileName, () => {}) // Ignore errors
    likely benign LLM, confidence 0.85 Imports a temporary bundled config file, then removes it.
    Reasoning

    Imports a temporary bundled config file and deletes it afterward. Standard config-bundling flow; the temp file is built from the project's own config.

  18. info warn → info by review dynamic-import packages/vite/src/node/plugins/css.ts:2554:31

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

          const sssPath = loadPreprocessorPath(PostCssDialectLang.sss, root)
          const resolved = (await import(pathToFileURL(sssPath).href)).default
          return (cachedSss = resolved)
        })()
    likely benign LLM, confidence 0.87 Loads an optional stylus/sss preprocessor package by resolved path.
    Reasoning

    Loads the optional sass-like preprocessor from a resolved path, a standard optional-peer-dependency pattern in Vite's CSS plugin.

  19. info warn → info by review dynamic-import packages/vite/src/node/plugins/css.ts:2607:39

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        async run(sassPath, data, options) {
          const sass: typeof Sass = await import(sassPath)
          compilerPromise ??= sass.initAsyncCompiler()
          const compiler = await compilerPromise
    likely benign LLM, confidence 0.87 Imports the Sass compiler from a resolved path.
    Reasoning

    Loads the user-installed Sass compiler from a resolved path, the expected preprocessor loading behavior.

  20. info warn → info by review dynamic-import packages/vite/src/node/plugins/css.ts:2714:17

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

            try {
              await import(sassPackage.path)
            } catch (e) {
              if (/sass-embedded-[a-z0-9]+-[a-z0-9]+/i.test(e.message)) {
    likely benign LLM, confidence 0.85 Tries to import the sass-embedded package and handles load errors.
    Reasoning

    Probes whether the sass-embedded package loads, catching errors to detect an alternative package. Ordinary optional-dependency probing with no malicious indicators.

  21. info warn → info by review dynamic-import packages/vite/src/node/plugins/css.ts:2965:46

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

          ) => {
            const nodeLess: typeof Less = (await import(lessPath)).default
            const viteResolverPlugin = createViteLessPlugin(
              nodeLess,
    likely benign LLM, confidence 0.90 Lazy loads the Less preprocessor from a resolved path.
    Reasoning

    Dynamic import of a resolved preprocessor path (lessPath) in Vite's CSS plugin is a standard lazy-loading pattern for an optional peer dependency; not obfuscation.

  22. info warn → info by review dynamic-import packages/vite/src/node/plugins/css.ts:3078:46

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

          ) => {
            const stylus: typeof Stylus = (await import(stylusPath)).default
    
            const ref = stylus(content, {
    likely benign LLM, confidence 0.90 Lazy loads the Stylus preprocessor from a resolved path.
    Reasoning

    Same pattern as Less: lazy import of the Stylus preprocessor from a resolved module path, a legitimate optional-dependency load.

  23. info warn → info by review dynamic-import packages/vite/src/node/plugins/terser.ts:49:57

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

            ) => {
              const terser: typeof import('terser') = await import(terserPath)
              try {
                return (await terser.minify(code, options)) as TerserMinifyOutput
    likely benign LLM, confidence 0.90 Lazy loads terser minifier from a resolved path.
    Reasoning

    Terser is dynamically imported from a resolved path to keep it optional; the minify call operates on build output. Ordinary tooling code.

  24. info warn → info by review dynamic-execution packages/vite/src/node/plugins/wasm.ts:43:28

    `atob` decodes a base64 value at runtime — common step before dynamic fetch or eval (ast pass, confidence 0.75)

        } else if (typeof atob === 'function') {
          const binaryString = atob(urlContent)
          bytes = new Uint8Array(binaryString.length)
          for (let i = 0; i < binaryString.length; i++) {
    likely benign LLM, confidence 0.85 Decodes base64 wasm data URL content into bytes.
    Reasoning

    atob decodes a base64 WASM data URL in a Vite plugin to produce bytes for WebAssembly instantiation. This is a standard, expected decoding step with no evidence of hidden payload execution.

  25. dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

    export async function importAction(id) {
      return await import(/* @vite-ignore */ id)
    }
    likely benign LLM, confidence 0.90 Test fixture performing dynamic import of a passed id.
    Reasoning

    A test fixture deliberately exercising dynamic import with an ignore annotation for the SSR runtime; expected behavior in tests.

  26. dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        dynamicProcessed: await import('./simple'),
        dynamicRelative: await import(nameRelative),
        dynamicAbsolute: await import(nameAbsolute),
        dynamicAbsoluteExtension: await import(nameAbsoluteExtension),
    likely benign LLM, confidence 0.92 Test fixture dynamic import of a relative module name.
    Reasoning

    Test fixture covering various dynamic import forms for the SSR module runner; the specifiers are test-controlled relative paths.

  27. dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        dynamicRelative: await import(nameRelative),
        dynamicAbsolute: await import(nameAbsolute),
        dynamicAbsoluteExtension: await import(nameAbsoluteExtension),
        dynamicAbsoluteFull: await import(
    likely benign LLM, confidence 0.92 Test fixture dynamic import of an absolute module name.
    Reasoning

    Same test fixture covering dynamic import variants; not malicious.

  28. dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        dynamicAbsolute: await import(nameAbsolute),
        dynamicAbsoluteExtension: await import(nameAbsoluteExtension),
        dynamicAbsoluteFull: await import(
          (process.platform === 'win32' ? '/@fs/' : '') + absolutePath
    likely benign LLM, confidence 0.92 Test fixture dynamic import of a platform-adjusted absolute path.
    Reasoning

    Test fixture building a /@fs/ path by platform for dynamic import; benign test coverage of path handling.

  29. dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        dynamicAbsoluteExtension: await import(nameAbsoluteExtension),
        dynamicAbsoluteFull: await import(
          (process.platform === 'win32' ? '/@fs/' : '') + absolutePath
        ),
    likely benign LLM, confidence 0.92 Test fixture dynamic import of an absolute path with extension.
    Reasoning

    Same test fixture, dynamic import with extension variant; benign.

  30. dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        ),
        dynamicFileUrl: await import(fileUrl),
        static: staticModule,
      }
    likely benign LLM, confidence 0.92 Test fixture dynamic import of a file URL.
    Reasoning

    Test fixture dynamic import of a file URL, part of a module-runner test; benign.

  31. base64-like blob (692 bytes, compression ratio 0.70) (in comment) (raw pass, confidence 0.36)

    //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidHJhbnNwaWxlZC1pbmxpbmUudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAnbm9kZTpwYXRoJ1xuXG5leHBvcnQgdHlwZSBEdW1teSA9IHtcbiAgZm9vOiBcImZvb1wiLFxufVxuXG4vKipcbiAqIGR1bW15XG4gKiBkdW1teVxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB0ZX
  32. `btoa` encodes a value as base64 at runtime — used in exfiltration patterns (ast pass, confidence 0.55)

        `throw new Error('example')\n` +
        `//# ${SOURCEMAPPING_URL}=data:application/json;base64,${btoa(
          JSON.stringify(syntheticSourceMap),
        )}\n`
  33. orphaned high surrogate \uD800 (no matching low surrogate) (token pass, confidence 0.65)

    function isHighSurrogate(value: string): boolean {
      return value >= '\uD800' && value <= '\uDBFF'
    }
  34. orphaned high surrogate \uDBFF (no matching low surrogate) (token pass, confidence 0.65)

    function isHighSurrogate(value: string): boolean {
      return value >= '\uD800' && value <= '\uDBFF'
    }

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.1.0
git clone https://github.com/vitejs/vite vite && cd vite
git checkout v8.3.5
disclude scan --severity info --diff v8.3.4 packages/vite