VYPR
Critical severityNVD Advisory· Published Mar 12, 2026· Updated Mar 13, 2026

Cross-Origin File Exfiltration via CORS Misconfiguration + Path Traversal in TinaCMS

CVE-2026-28792

Description

Tina is a headless content management system. Prior to 2.1.8 , the TinaCMS CLI dev server combines a permissive CORS configuration (Access-Control-Allow-Origin: *) with the path traversal vulnerability (previously reported) to enable a browser-based drive-by attack. A remote attacker can enumerate the filesystem, write arbitrary files, and delete arbitrary files on developer's machines by simply tricking them into visiting a malicious website while tinacms dev is running. This vulnerability is fixed in 2.1.8.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

TinaCMS CLI dev server prior to 2.1.8 had permissive CORS and path traversal, enabling remote file read/write/delete via browser drive-by attack.

Vulnerability

Overview

The TinaCMS CLI dev server prior to version 2.1.8 combined a permissive CORS configuration (Access-Control-Allow-Origin: *) with a path traversal vulnerability, allowing a browser-based drive-by attack on developer machines [1][4]. The CORS misconfiguration permitted any website to make cross-origin requests to the dev server, while the path traversal bug allowed accessing files outside the intended directory [4].

Attack

Vector

An attacker can exploit this by tricking a developer into visiting a malicious website while tinacms dev is running locally (default port 4001) [1]. The malicious site’s JavaScript can make fetch requests to http://localhost:4001/../../../etc/passwd (or similar paths), leveraging the CORS wildcard to read and exfiltrate sensitive files, write arbitrary files, or delete files [4]. No network exposure is required—the attack succeeds purely from within the browser on the same machine [4].

Impact

A remote attacker can enumerate the filesystem, write arbitrary files, and delete arbitrary files on the developer's machine [1][4]. This includes exfiltration of source code, credentials, and other sensitive data, potentially leading to supply chain compromise if malicious files are written to the project [4].

Mitigation

The vulnerability is fixed in TinaCMS version 2.1.8 [1]. The fix restricts CORS to localhost by default, adds a server.allowedOrigins config option for non-localhost environments, and enables Vite’s server.fs.strict with a computed allow list [2][3]. Users should upgrade immediately and avoid running tinacms dev while browsing untrusted sites if upgrading is not possible [4].

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@tinacms/clinpm
< 2.1.82.1.8

Affected products

2
  • Ssw/Tinacmsllm-fuzzy
    Range: <2.1.8
  • @tinacms/cliv5
    Range: < 2.1.8

Patches

1
56d533e610a5

Restricted CORS and Vite fs access on dev server (#6450)

https://github.com/tinacms/tinacmsIvan Gaiduk [SSW]Feb 25, 2026via ghsa
10 files changed · +370 48
  • .changeset/nasty-eels-compete.md+9 0 added
    @@ -0,0 +1,9 @@
    +---
    +"@tinacms/cli": patch
    +"@tinacms/schema-tools": patch
    +---
    +
    +* Restricted CORS on dev server to localhost by default for [GHSA-8pw3-9m7f-q734](https://github.com/tinacms/tinacms/security/advisories/GHSA-8pw3-9m7f-q734).
    +* Added `server.allowedOrigins` config option for non-localhost environments.
    +* Enabled Vite `server.fs.strict` with computed allow list for [GHSA-m48g-4wr2-j2h6](https://github.com/tinacms/tinacms/security/advisories/GHSA-m48g-4wr2-j2h6)
    +* Bind LevelDB TCP server to 127.0.0.1
    
  • packages/@tinacms/cli/src/cmds/init/templates/config.ts+6 0 modified
    @@ -138,6 +138,12 @@ export const generateConfig = (args: ConfigTemplateArgs) => {
           outputFolder: "admin",
           publicFolder: "${args.publicFolder}",
         },
    +    // Uncomment to allow cross-origin requests from non-localhost origins
    +    // during local development (e.g. GitHub Codespaces, Gitpod, Docker).
    +    // Use 'private' to allow all private-network IPs (WSL2, Docker, etc.)
    +    // server: {
    +    //   allowedOrigins: ['https://your-codespace.github.dev'],
    +    // },
         media: {
           tina: {
             mediaRoot: "",
    
  • packages/@tinacms/cli/src/next/database.ts+9 9 modified
    @@ -1,20 +1,20 @@
    +import { createServer } from 'net';
     import {
    -  createDatabaseInternal,
    -  FilesystemBridge,
    +  Bridge,
       Database,
    +  FilesystemBridge,
       TinaLevelClient,
    -  Bridge,
    +  createDatabaseInternal,
     } from '@tinacms/graphql';
    +import { ManyLevelHost } from 'many-level';
    +import { MemoryLevel } from 'memory-level';
    +import { pipeline } from 'readable-stream';
    +import { logger } from '../logger';
     import {
       ConfigManager,
       LEGACY_TINA_FOLDER,
       TINA_FOLDER,
     } from './config-manager';
    -import { logger } from '../logger';
    -import { pipeline } from 'readable-stream';
    -import { createServer } from 'net';
    -import { ManyLevelHost } from 'many-level';
    -import { MemoryLevel } from 'memory-level';
     
     export const createDBServer = (port: number) => {
       const levelHost = new ManyLevelHost(
    @@ -37,7 +37,7 @@ export const createDBServer = (port: number) => {
           );
         }
       });
    -  dbServer.listen(port);
    +  dbServer.listen(port, 'localhost');
     };
     
     export async function createAndInitializeDatabase(
    
  • packages/@tinacms/cli/src/next/vite/cors.test.ts+126 0 added
    @@ -0,0 +1,126 @@
    +import { buildCorsOriginCheck } from './cors';
    +
    +describe('buildCorsOriginCheck', () => {
    +  const check = (
    +    fn: ReturnType<typeof buildCorsOriginCheck>,
    +    origin: string | undefined
    +  ): Promise<boolean> =>
    +    new Promise((resolve) => {
    +      fn(origin, (_err, allow) => resolve(!!allow));
    +    });
    +
    +  describe('default (no allowedOrigins)', () => {
    +    const fn = buildCorsOriginCheck();
    +
    +    it('allows requests with no Origin header', async () => {
    +      expect(await check(fn, undefined)).toBe(true);
    +    });
    +
    +    it('allows http://localhost', async () => {
    +      expect(await check(fn, 'http://localhost')).toBe(true);
    +    });
    +
    +    it('allows http://localhost:3000', async () => {
    +      expect(await check(fn, 'http://localhost:3000')).toBe(true);
    +    });
    +
    +    it('allows http://127.0.0.1:4001', async () => {
    +      expect(await check(fn, 'http://127.0.0.1:4001')).toBe(true);
    +    });
    +
    +    it('allows http://[::1]:4001', async () => {
    +      expect(await check(fn, 'http://[::1]:4001')).toBe(true);
    +    });
    +
    +    it('blocks https://evil.com', async () => {
    +      expect(await check(fn, 'https://evil.com')).toBe(false);
    +    });
    +
    +    it('blocks http://172.20.0.5:3000 (private IP without keyword)', async () => {
    +      expect(await check(fn, 'http://172.20.0.5:3000')).toBe(false);
    +    });
    +  });
    +
    +  describe('with exact origin strings', () => {
    +    const fn = buildCorsOriginCheck(['https://my-codespace.github.dev']);
    +
    +    it('allows the configured origin', async () => {
    +      expect(await check(fn, 'https://my-codespace.github.dev')).toBe(true);
    +    });
    +
    +    it('still allows localhost', async () => {
    +      expect(await check(fn, 'http://localhost:3000')).toBe(true);
    +    });
    +
    +    it('blocks other origins', async () => {
    +      expect(await check(fn, 'https://evil.com')).toBe(false);
    +    });
    +  });
    +
    +  describe('with "private" keyword', () => {
    +    const fn = buildCorsOriginCheck(['private']);
    +
    +    it('allows 10.x.x.x (RFC 1918)', async () => {
    +      expect(await check(fn, 'http://10.0.0.1:3000')).toBe(true);
    +    });
    +
    +    it('allows 172.16-31.x.x (RFC 1918)', async () => {
    +      expect(await check(fn, 'http://172.20.0.5:4001')).toBe(true);
    +    });
    +
    +    it('allows 192.168.x.x (RFC 1918)', async () => {
    +      expect(await check(fn, 'http://192.168.1.100:3000')).toBe(true);
    +    });
    +
    +    it('blocks 172.15.x.x (not RFC 1918)', async () => {
    +      expect(await check(fn, 'http://172.15.0.1:3000')).toBe(false);
    +    });
    +
    +    it('blocks 172.32.x.x (not RFC 1918)', async () => {
    +      expect(await check(fn, 'http://172.32.0.1:3000')).toBe(false);
    +    });
    +
    +    it('blocks public IPs', async () => {
    +      expect(await check(fn, 'http://8.8.8.8:3000')).toBe(false);
    +    });
    +
    +    it('blocks domains', async () => {
    +      expect(await check(fn, 'https://evil.com')).toBe(false);
    +    });
    +
    +    it('still allows localhost', async () => {
    +      expect(await check(fn, 'http://localhost:3000')).toBe(true);
    +    });
    +  });
    +
    +  describe('with "private" keyword plus extra origins', () => {
    +    const fn = buildCorsOriginCheck([
    +      'private',
    +      'https://my-codespace.github.dev',
    +    ]);
    +
    +    it('allows private IPs', async () => {
    +      expect(await check(fn, 'http://192.168.1.5:3000')).toBe(true);
    +    });
    +
    +    it('allows the extra origin', async () => {
    +      expect(await check(fn, 'https://my-codespace.github.dev')).toBe(true);
    +    });
    +
    +    it('blocks other origins', async () => {
    +      expect(await check(fn, 'https://evil.com')).toBe(false);
    +    });
    +  });
    +
    +  describe('with RegExp entries', () => {
    +    const fn = buildCorsOriginCheck([/^https:\/\/.*\.preview\.app$/]);
    +
    +    it('allows matching origins', async () => {
    +      expect(await check(fn, 'https://foo.preview.app')).toBe(true);
    +    });
    +
    +    it('blocks non-matching origins', async () => {
    +      expect(await check(fn, 'https://evil.com')).toBe(false);
    +    });
    +  });
    +});
    
  • packages/@tinacms/cli/src/next/vite/cors.ts+64 0 added
    @@ -0,0 +1,64 @@
    +/**
    + * Shared CORS origin-checking logic for the TinaCMS dev server.
    + *
    + * By default only localhost / 127.0.0.1 / [::1] (any port) are allowed.
    + * Users can extend this via `server.allowedOrigins` in their tina config.
    + * The special keyword `'private'` expands to all RFC 1918 private-network
    + * IP ranges (10.x, 172.16-31.x, 192.168.x) — useful for WSL2, Docker
    + * bridge networks, etc.
    + */
    +
    +const LOCALHOST_RE = /^https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/;
    +
    +// RFC 1918 private networks: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
    +const PRIVATE_NETWORK_RE =
    +  /^https?:\/\/(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})(:\d+)?$/;
    +
    +/**
    + * Expand a raw `allowedOrigins` array: replace the `'private'` keyword
    + * with the RFC 1918 regex and keep everything else as-is.
    + */
    +function expandOrigins(raw: (string | RegExp)[]): (string | RegExp)[] {
    +  const hasPrivate = raw.some((o) => o === 'private');
    +  const filtered = raw.filter((o) => o !== 'private');
    +  return hasPrivate ? [...filtered, PRIVATE_NETWORK_RE] : filtered;
    +}
    +
    +/**
    + * Build a CORS `origin` callback compatible with the `cors` npm package.
    + */
    +export function buildCorsOriginCheck(
    +  allowedOrigins: (string | RegExp)[] = []
    +): (
    +  origin: string | undefined,
    +  callback: (err: Error | null, allow?: boolean) => void
    +) => void {
    +  const extra = expandOrigins(allowedOrigins);
    +
    +  return (origin, callback) => {
    +    // Allow requests with no Origin header (curl, same-origin, etc.).
    +    if (!origin) {
    +      callback(null, true);
    +      return;
    +    }
    +    if (LOCALHOST_RE.test(origin)) {
    +      callback(null, true);
    +      return;
    +    }
    +    for (const allowed of extra) {
    +      if (typeof allowed === 'string') {
    +        if (allowed === origin) {
    +          callback(null, true);
    +          return;
    +        }
    +      } else {
    +        allowed.lastIndex = 0;
    +        if (allowed.test(origin)) {
    +          callback(null, true);
    +          return;
    +        }
    +      }
    +    }
    +    callback(null, false);
    +  };
    +}
    
  • packages/@tinacms/cli/src/next/vite/index.test.ts+81 21 modified
    @@ -16,10 +16,10 @@ jest.mock('vite', () => ({
       splitVendorChunkPlugin: () => ({ name: 'mock-split-vendor' }),
     }));
     
    -import { createConfig } from './index';
    -import * as filterPublicEnvModule from './filterPublicEnv';
    -import type { ConfigManager } from '../config-manager';
     import type { Database } from '@tinacms/graphql';
    +import type { ConfigManager } from '../config-manager';
    +import * as filterPublicEnvModule from './filterPublicEnv';
    +import { createConfig } from './index';
     
     /** Minimal stub satisfying the properties createConfig reads. */
     function stubConfigManager(): ConfigManager {
    @@ -65,7 +65,7 @@ const FAKE_PUBLIC_ENV = {
       HEAD: 'main',
     };
     
    -describe('createConfig integration', () => {
    +describe('createConfig', () => {
       let spy: jest.SpyInstance;
     
       beforeAll(() => {
    @@ -78,57 +78,117 @@ describe('createConfig integration', () => {
         spy.mockRestore();
       });
     
    -  it('calls filterPublicEnv', async () => {
    -    await createConfig({
    +  it('embeds the filterPublicEnv result into define["process.env"]', async () => {
    +    const config = await createConfig({
           configManager: stubConfigManager(),
           database: {} as Database,
           apiURL: 'http://localhost:4001/graphql',
           noWatch: true,
         });
    +    const raw = config.define!['process.env'];
     
    -    expect(spy).toHaveBeenCalled();
    +    expect(raw).toBe(`new Object(${JSON.stringify(FAKE_PUBLIC_ENV)})`);
       });
     
    -  it('embeds the filterPublicEnv result into define["process.env"]', async () => {
    +  it('does not embed any values outside the filterPublicEnv result', async () => {
    +    spy.mockReturnValue({ TINA_PUBLIC_ONLY: 'safe' });
    +
         const config = await createConfig({
           configManager: stubConfigManager(),
           database: {} as Database,
           apiURL: 'http://localhost:4001/graphql',
           noWatch: true,
         });
         const raw = config.define!['process.env'];
    +    const jsonStr = raw.replace(/^new Object\(/, '').replace(/\)$/, '');
    +    const env = JSON.parse(jsonStr);
     
    -    expect(raw).toBe(`new Object(${JSON.stringify(FAKE_PUBLIC_ENV)})`);
    +    expect(Object.keys(env)).toEqual(['TINA_PUBLIC_ONLY']);
       });
     
    -  it('contains only the keys returned by filterPublicEnv', async () => {
    +  it('sets server.fs.strict to true', async () => {
         const config = await createConfig({
           configManager: stubConfigManager(),
           database: {} as Database,
           apiURL: 'http://localhost:4001/graphql',
           noWatch: true,
         });
    -    const raw = config.define!['process.env'];
    -    const jsonStr = raw.replace(/^new Object\(/, '').replace(/\)$/, '');
    -    const env = JSON.parse(jsonStr);
     
    -    expect(env).toEqual(FAKE_PUBLIC_ENV);
    +    expect(config.server!.fs!.strict).toBe(true);
       });
     
    -  it('does not embed any values outside the filterPublicEnv result', async () => {
    -    spy.mockReturnValue({ TINA_PUBLIC_ONLY: 'safe' });
    +  it('allows spaRootPath and rootPath in server.fs', async () => {
    +    const cm = stubConfigManager();
    +    const config = await createConfig({
    +      configManager: cm,
    +      database: {} as Database,
    +      apiURL: 'http://localhost:4001/graphql',
    +      noWatch: true,
    +    });
    +
    +    expect(config.server!.fs!.allow).toContain(cm.spaRootPath);
    +    expect(config.server!.fs!.allow).toContain(cm.rootPath);
    +  });
     
    +  it('allows contentRootPath when it differs from rootPath', async () => {
    +    const cm = stubConfigManager();
    +    (cm as any).contentRootPath = '/fake/content-repo';
    +    const config = await createConfig({
    +      configManager: cm,
    +      database: {} as Database,
    +      apiURL: 'http://localhost:4001/graphql',
    +      noWatch: true,
    +    });
    +
    +    expect(config.server!.fs!.allow).toContain('/fake/content-repo');
    +  });
    +
    +  it('does not duplicate rootPath when contentRootPath equals rootPath', async () => {
    +    const cm = stubConfigManager();
    +    (cm as any).contentRootPath = cm.rootPath;
    +    const config = await createConfig({
    +      configManager: cm,
    +      database: {} as Database,
    +      apiURL: 'http://localhost:4001/graphql',
    +      noWatch: true,
    +    });
    +
    +    const rootOccurrences = config.server!.fs!.allow!.filter(
    +      (p) => p === cm.rootPath
    +    );
    +    expect(rootOccurrences).toHaveLength(1);
    +  });
    +
    +  it('sets server.cors.origin from buildCorsOriginCheck', async () => {
         const config = await createConfig({
           configManager: stubConfigManager(),
           database: {} as Database,
           apiURL: 'http://localhost:4001/graphql',
           noWatch: true,
         });
    -    const raw = config.define!['process.env'];
    -    const jsonStr = raw.replace(/^new Object\(/, '').replace(/\)$/, '');
    -    const env = JSON.parse(jsonStr);
     
    -    expect(Object.keys(env)).toEqual(['TINA_PUBLIC_ONLY']);
    -    expect(env.TINA_PUBLIC_ONLY).toBe('safe');
    +    expect(typeof (config.server!.cors as any).origin).toBe('function');
    +  });
    +
    +  it('passes server.allowedOrigins through to the CORS callback', async () => {
    +    const cm = stubConfigManager();
    +    (cm.config as any).server = {
    +      allowedOrigins: ['https://my-codespace.github.dev'],
    +    };
    +
    +    const config = await createConfig({
    +      configManager: cm,
    +      database: {} as Database,
    +      apiURL: 'http://localhost:4001/graphql',
    +      noWatch: true,
    +    });
    +
    +    const originFn = (config.server!.cors as any).origin;
    +    const allowed = await new Promise<boolean>((resolve) => {
    +      originFn('https://my-codespace.github.dev', (_err: any, allow: boolean) =>
    +        resolve(!!allow)
    +      );
    +    });
    +    expect(allowed).toBe(true);
       });
     });
    
  • packages/@tinacms/cli/src/next/vite/index.ts+20 1 modified
    @@ -10,6 +10,7 @@ import {
       splitVendorChunkPlugin,
     } from 'vite';
     import type { ConfigManager } from '../config-manager';
    +import { buildCorsOriginCheck } from './cors';
     import { filterPublicEnv } from './filterPublicEnv';
     import { tinaTailwind } from './tailwind';
     
    @@ -202,6 +203,13 @@ export const createConfig = async ({
         },
         server: {
           host: configManager.config?.build?.host ?? false,
    +      // Restrict Vite's built-in CORS to the same origins our custom
    +      // middleware allows (localhost + user-configured allowedOrigins).
    +      cors: {
    +        origin: buildCorsOriginCheck(
    +          configManager.config?.server?.allowedOrigins
    +        ),
    +      },
           watch: noWatch
             ? {
                 ignored: ['**/*'],
    @@ -213,7 +221,18 @@ export const createConfig = async ({
                 ],
               },
           fs: {
    -        strict: false,
    +        strict: true,
    +        // Allow serving files from the project root and the SPA package.
    +        // Without this, Vite would block access to tina config/generated
    +        // files since the Vite root is the @tinacms/app package directory.
    +        allow: [
    +          configManager.spaRootPath,
    +          configManager.rootPath,
    +          ...(configManager.contentRootPath &&
    +          configManager.contentRootPath !== configManager.rootPath
    +            ? [configManager.contentRootPath]
    +            : []),
    +        ],
           },
         },
         build: {
    
  • packages/@tinacms/cli/src/next/vite/plugins.ts+21 11 modified
    @@ -1,21 +1,22 @@
    -import AsyncLock from 'async-lock';
    -import type { Plugin } from 'vite';
    -import { createFilter, FilterPattern } from '@rollup/pluginutils';
    -import type { Config } from '@svgr/core';
     import fs from 'fs';
    -import { transformWithEsbuild } from 'vite';
    -import { transform as esbuildTransform } from 'esbuild';
     import path from 'path';
    -import bodyParser from 'body-parser';
    -import cors from 'cors';
    +import { FilterPattern, createFilter } from '@rollup/pluginutils';
    +import type { Config } from '@svgr/core';
     import { resolve as gqlResolve } from '@tinacms/graphql';
     import type { Database } from '@tinacms/graphql';
    +import AsyncLock from 'async-lock';
    +import bodyParser from 'body-parser';
    +import cors from 'cors';
    +import { transform as esbuildTransform } from 'esbuild';
    +import type { Plugin } from 'vite';
    +import { transformWithEsbuild } from 'vite';
     import {
    -  parseMediaFolder,
       createMediaRouter,
    +  parseMediaFolder,
     } from '../commands/dev-command/server/media';
    -import type { ConfigManager } from '../config-manager';
     import { createSearchIndexRouter } from '../commands/dev-command/server/searchIndex';
    +import type { ConfigManager } from '../config-manager';
    +import { buildCorsOriginCheck } from './cors';
     
     export const transformTsxPlugin = ({
       configManager: _configManager,
    @@ -59,10 +60,19 @@ export const devServerEndPointsPlugin = ({
       searchIndex: any;
       databaseLock: (fn: () => Promise<void>) => Promise<void>;
     }) => {
    +  const corsOriginCheck = buildCorsOriginCheck(
    +    configManager.config?.server?.allowedOrigins
    +  );
    +
       const plug: Plugin = {
         name: 'graphql-endpoints',
         configureServer(server) {
    -      server.middlewares.use(cors());
    +      server.middlewares.use(
    +        cors({
    +          origin: corsOriginCheck,
    +          methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
    +        })
    +      );
           server.middlewares.use(bodyParser.json({ limit: '5mb' }));
           server.middlewares.use(async (req, res, next: Function) => {
             const mediaPaths = configManager.config.media?.tina;
    
  • packages/@tinacms/cli/src/server/server.ts+11 6 modified
    @@ -2,16 +2,17 @@
     
     */
     
    -import path from 'node:path';
    -import cors from 'cors';
     import http from 'node:http';
    -import express from 'express';
    +import path from 'node:path';
    +import type { Database } from '@tinacms/graphql';
     import { altairExpress } from 'altair-express-middleware';
     // @ts-ignore
     import bodyParser from 'body-parser';
    -import type { Database } from '@tinacms/graphql';
    -import { createMediaRouter } from './routes';
    +import cors from 'cors';
    +import express from 'express';
    +import { buildCorsOriginCheck } from '../next/vite/cors';
     import { parseMediaFolder } from '../utils';
    +import { createMediaRouter } from './routes';
     
     export const gqlServer = async (database, verbose: boolean) => {
       // This is lazily required so we can update the module
    @@ -20,7 +21,11 @@ export const gqlServer = async (database, verbose: boolean) => {
     
       const app = express();
       const server = http.createServer(app);
    -  app.use(cors());
    +  app.use(
    +    cors({
    +      origin: buildCorsOriginCheck(),
    +    })
    +  );
       app.use(bodyParser.json());
     
       app.use(
    
  • packages/@tinacms/schema-tools/src/types/index.ts+23 0 modified
    @@ -748,6 +748,29 @@ export interface Config<
          */
         basePath?: string;
       };
    +  /**
    +   * Configuration for the local development server (`tinacms dev`).
    +   * Has no effect on production deployments.
    +   */
    +  server?: {
    +    /**
    +     * Origins allowed to make cross-origin requests to the dev server.
    +     * Defaults to localhost / 127.0.0.1 / [::1] only. Each entry can be a string,
    +     * RegExp, or `'private'` (expands to RFC 1918 private-network IPs).
    +     *
    +     * @example
    +     * ```ts
    +     * server: { allowedOrigins: ['https://my-codespace.github.dev'] }
    +     * ```
    +     *
    +     * @example
    +     * ```ts
    +     * server: { allowedOrigins: ['private'] }
    +     * ```
    +     *
    +     */
    +    allowedOrigins?: (RegExp | 'private' | (string & {}))[];
    +  };
       media?:
         | {
             /**
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.