GHSA-648H-GW55-M2G7

Vulnerability from github – Published: 2026-10-30 23:00 – Updated: 2026-10-30 23:00
VLAI
Summary
Nuxt dev server exposes private runtime config through the Nitro dev bundle
Details

Summary

With Nitro 2 (the default server engine in Nuxt 3 and Nuxt 4), the Nitro development server bundle written by nuxt dev can be fetched through the Vite dev server. Nitro inlines the resolved runtimeConfig into that bundle, so private runtime config values that were resolved at build time can be read by anyone with HTTP access to the dev server.

Impact

nuxt dev writes the Nitro development server bundle to <buildDir>/dev/index.mjs (by default .nuxt/dev/index.mjs). The build directory is inside the directories Nuxt passes to Vite's server.fs.allow, so the bundle is served by the dev server:

curl http://<dev-server>/_nuxt/@fs/<absolute-path-to-project>/.nuxt/dev/index.mjs

The response contains every private (non-public) runtime config value that was resolved at build time. That includes values set in nuxt.config, such as a secret read from .env:

export default defineNuxtConfig({
  runtimeConfig: {
    apiSecret: process.env.API_SECRET,
  },
})

From Nuxt 4.6.0, it also includes the generated development appSecret. Vite's default deny list blocks .env itself, but not the bundle containing values read from it.

Exploitation requires direct HTTP access to the dev server. nuxt dev listens on localhost by default, so this mainly affects dev servers that are exposed to a network (for example with --host, a published container port or a tunnel). As far as we can tell, a malicious website cannot read the file through a developer's browser: Vite's CORS and host checks prevent pages on other origins from reading the response.

Production builds are not affected, because the Vite dev server is not used and the server bundle is not served. Nuxt projects using Nitro 3 do not write the server bundle to disk in development and are not affected. Private runtime config values that are left empty in nuxt.config and supplied through NUXT_* environment variables are applied when the server starts, are not inlined into the bundle, and are not exposed.

Patches

Fixed in @nuxt/vite-builder 4.6.3, which nuxt 4.6.3 depends on. The dev server now adds Nitro's development output directory to Vite's server.fs.deny, keeping Vite's default deny list.

Nuxt 3 has reached end of life and will not receive a fix.

Workarounds

Avoid exposing the dev server to untrusted networks. Alternatively, set private runtime config keys to an empty default in nuxt.config and provide their values with the matching NUXT_* environment variables (for example runtimeConfig: { apiSecret: '' } with NUXT_API_SECRET in .env).

If a dev server has been reachable by untrusted clients, rotate any credentials that were set through runtimeConfig in nuxt.config.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@nuxt/vite-builder"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.0.0"
            },
            {
              "fixed": "4.6.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-119199"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-538",
      "CWE-552"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-30T23:00:43Z",
    "nvd_published_at": "2026-10-29T21:17:18Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\n\nWith Nitro 2 (the default server engine in Nuxt 3 and Nuxt 4), the Nitro development server bundle written by `nuxt dev` can be fetched through the Vite dev server. Nitro inlines the resolved `runtimeConfig` into that bundle, so private runtime config values that were resolved at build time can be read by anyone with HTTP access to the dev server.\n\n### Impact\n\n`nuxt dev` writes the Nitro development server bundle to `\u003cbuildDir\u003e/dev/index.mjs` (by default `.nuxt/dev/index.mjs`). The build directory is inside the directories Nuxt passes to Vite\u0027s `server.fs.allow`, so the bundle is served by the dev server:\n\n```bash\ncurl http://\u003cdev-server\u003e/_nuxt/@fs/\u003cabsolute-path-to-project\u003e/.nuxt/dev/index.mjs\n```\n\nThe response contains every private (non-`public`) runtime config value that was resolved at build time. That includes values set in `nuxt.config`, such as a secret read from `.env`:\n\n```ts\nexport default defineNuxtConfig({\n  runtimeConfig: {\n    apiSecret: process.env.API_SECRET,\n  },\n})\n```\n\nFrom Nuxt 4.6.0, it also includes the generated development `appSecret`. Vite\u0027s default deny list blocks `.env` itself, but not the bundle containing values read from it.\n\nExploitation requires direct HTTP access to the dev server. `nuxt dev` listens on localhost by default, so this mainly affects dev servers that are exposed to a network (for example with `--host`, a published container port or a tunnel). As far as we can tell, a malicious website cannot read the file through a developer\u0027s browser: Vite\u0027s CORS and host checks prevent pages on other origins from reading the response.\n\nProduction builds are not affected, because the Vite dev server is not used and the server bundle is not served. Nuxt projects using Nitro 3 do not write the server bundle to disk in development and are not affected. Private runtime config values that are left empty in `nuxt.config` and supplied through `NUXT_*` environment variables are applied when the server starts, are not inlined into the bundle, and are not exposed.\n\n### Patches\n\nFixed in `@nuxt/vite-builder` 4.6.3, which `nuxt` 4.6.3 depends on. The dev server now adds Nitro\u0027s development output directory to Vite\u0027s `server.fs.deny`, keeping Vite\u0027s default deny list.\n\nNuxt 3 has reached end of life and will not receive a fix.\n\n### Workarounds\n\nAvoid exposing the dev server to untrusted networks. Alternatively, set private runtime config keys to an empty default in `nuxt.config` and provide their values with the matching `NUXT_*` environment variables (for example `runtimeConfig: { apiSecret: \u0027\u0027 }` with `NUXT_API_SECRET` in `.env`).\n\nIf a dev server has been reachable by untrusted clients, rotate any credentials that were set through `runtimeConfig` in `nuxt.config`.",
  "id": "GHSA-648h-gw55-m2g7",
  "modified": "2026-10-30T23:00:43Z",
  "published": "2026-10-30T23:00:43Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nuxt/nuxt/security/advisories/GHSA-648h-gw55-m2g7"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-119199"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nuxt/nuxt/commit/12b58f9d8768682611c3ad4ea4d403875129dbca"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nuxt/nuxt"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nuxt/nuxt/releases/tag/v4.6.3"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Nuxt dev server exposes private runtime config through the Nitro dev bundle"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    Loading…

    Related by attack behaviour

    Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.