GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-2P39-2JF3-FV2Q

Vulnerability from github – Published: 2026-08-20 18:35 – Updated: 2026-08-20 18:35
VLAI
Summary
next-video: Unauthenticated arbitrary file read via /api/video request handler
Details

Impact

The HTTP route handler exported by next-video/request-handler — which the README instructs consumers to mount at /api/video — allows an unauthenticated remote attacker to read arbitrary .json files from the production filesystem of any application following the documented setup.

The handler's GET endpoint accepts a url query parameter and uses it to locate and serve a JSON asset descriptor from disk. The only guard between "remote URL" and "local file path" is a regex check for ^https?://. Any value that does not match that prefix is treated as a local path, .json is appended, and the file is read with fs.readFile and returned in the HTTP response — with no authentication, no path canonicalization, and no traversal guard.

On a typical Next.js deployment this exposes, at minimum: - The Next.js Server Actions AES encryption key (.next/server/server-reference-manifest.json) - The Next.js Preview/Draft Mode keys (previewModeId, previewModeSigningKey, previewModeEncryptionKey) - Internal build manifests, route registries, and absolute runtime paths - Application-specific asset metadata (e.g. Mux uploadId, assetId, playbackId values stored in videos/*.json)

Any application that mounted /api/video following the documented one-liner is affected.

Patches

2.8.1

Workarounds

Until a patched version is available, wrap the exported handler in your own route file and validate the url parameter before passing it through:

  • Reject any url value that does not begin with https://, or that does not match a known allowlist of trusted remote hosts.
  • Alternatively, remove the /api/video route entirely if your application only uses build-time import of local video files and does not use <Video src="https://..."> with string URLs at runtime.

References

  • src/request-handler.ts — the vulnerable GET handler
  • src/assets.tsgetAssetPath(), where the local-vs-remote branching occurs
  • src/utils/utils.tsisRemote(), the sole guard between the two branches
  • src/config.tsloadAsset(), which performs the unconstrained fs.readFile
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2.8.0"
      },
      "package": {
        "ecosystem": "npm",
        "name": "next-video"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.8.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54150"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-20T18:35:11Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Impact\n\nThe HTTP route handler exported by `next-video/request-handler` \u2014 which the README instructs consumers to mount at `/api/video` \u2014 allows an unauthenticated remote attacker to read arbitrary `.json` files from the production filesystem of any application following the documented setup.\n\nThe handler\u0027s `GET` endpoint accepts a `url` query parameter and uses it to locate and serve a JSON asset descriptor from disk. The only guard between \"remote URL\" and \"local file path\" is a regex check for `^https?://`. Any value that does not match that prefix is treated as a local path, `.json` is appended, and the file is read with `fs.readFile` and returned in the HTTP response \u2014 with no authentication, no path canonicalization, and no traversal guard.\n\nOn a typical Next.js deployment this exposes, at minimum:\n- The **Next.js Server Actions AES encryption key** (`.next/server/server-reference-manifest.json`)\n- The **Next.js Preview/Draft Mode keys** (`previewModeId`, `previewModeSigningKey`, `previewModeEncryptionKey`)\n- Internal build manifests, route registries, and absolute runtime paths\n- Application-specific asset metadata (e.g. Mux `uploadId`, `assetId`, `playbackId` values stored in `videos/*.json`)\n\nAny application that mounted `/api/video` following the documented one-liner is affected.\n\n### Patches\n\n2.8.1\n\n### Workarounds\n\nUntil a patched version is available, wrap the exported handler in your own route file and validate the `url` parameter before passing it through:\n\n- Reject any `url` value that does not begin with `https://`, or that does not match a known allowlist of trusted remote hosts.\n- Alternatively, remove the `/api/video` route entirely if your application only uses build-time `import` of local video files and does not use `\u003cVideo src=\"https://...\"\u003e` with string URLs at runtime.\n\n### References\n\n- `src/request-handler.ts` \u2014 the vulnerable GET handler\n- `src/assets.ts` \u2014 `getAssetPath()`, where the local-vs-remote branching occurs\n- `src/utils/utils.ts` \u2014 `isRemote()`, the sole guard between the two branches\n- `src/config.ts` \u2014 `loadAsset()`, which performs the unconstrained `fs.readFile`",
  "id": "GHSA-2p39-2jf3-fv2q",
  "modified": "2026-08-20T18:35:11Z",
  "published": "2026-08-20T18:35:11Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/muxinc/next-video/security/advisories/GHSA-2p39-2jf3-fv2q"
    },
    {
      "type": "WEB",
      "url": "https://github.com/muxinc/next-video/commit/73abf1d534c2ac48db546ecfed0e89cbaf124f6f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/muxinc/next-video"
    },
    {
      "type": "WEB",
      "url": "https://github.com/muxinc/next-video/releases/tag/v2.8.1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "next-video: Unauthenticated arbitrary file read via /api/video request handler"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

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.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…