CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-108261

CVE-2026-108261: Admin Preview Cross-Origin Bypass and GraphQL Hijacking in TinaCMS

Alon Barad
Alon Barad
Software Engineer

Oct 10, 2026·5 min read·5 visits

Executive Summary (TL;DR)

TinaCMS admin preview dynamically loaded external origins from hash routing parameters and trusted postMessage traffic from those origins, allowing remote attackers to run arbitrary GraphQL operations on behalf of logged-in editors.

A critical origin validation flaw in TinaCMS admin preview allows unauthenticated attackers to bypass cross-origin postMessage checks and execute unauthorized GraphQL queries and mutations under an authenticated editor's context.

Vulnerability Overview

TinaCMS is an open-source headless Content Management System (CMS) that integrates real-time editing and content management features directly into React applications. A security flaw identified as CVE-2026-108261 exists in the admin preview routing interface of TinaCMS packages tinacms and @tinacms/app.

The vulnerability stems from insufficient validation of client-side routing parameters when constructing the embedded preview frame. When rendering the admin interface, the application extracts path information from the URL hash fragment and injects it into an <iframe> element intended to preview published or drafted content.

By crafting the hash fragment in a link, an unauthenticated remote attacker can force the host application to load an external, attacker-controlled origin into the preview frame while simultaneously trusting cross-origin postMessage requests from that frame.

Root Cause Analysis

The root cause of CVE-2026-108261 lies in two distinct implementation flaws: unsafe routing parameter prepending and dynamic self-referential origin determination for postMessage security.

In packages/tinacms/src/admin/index.tsx, the admin preview route uses React Router's splat parameter (params['*']) to set the source URL for the preview frame. The application originally initialized this source URL by prepending a single forward slash to the splat parameter: /${params['*']}. When an attacker provides leading slashes or backslashes in the hash fragment (such as #/~//attacker.com), string concatenation converts the relative path into a protocol-relative absolute URL (//attacker.com).

Simultaneously, packages/@tinacms/app/src/lib/preview-origin.ts implemented getExpectedPreviewOrigin, which extracted the expected postMessage origin directly from the iframe URL itself. When the iframe source was set to //attacker.com, new URL('//attacker.com', baseOrigin).origin resolved to https://attacker.com. As a result, the admin GraphQL reducer set its expected communication origin to https://attacker.com, accepting arbitrary administrative GraphQL read and write requests initiated by the external page.

Code Analysis & Patch Mechanics

To remediate the vulnerability, commit b57dbf4b56201aef15cd92caa49fd12ab96bbecf refactored origin determination and added strict path resolution checks.

In @tinacms/app, getExpectedPreviewOrigin was removed and replaced with getPreviewOrigin(), enforcing that the expected frame origin strictly matches window.location.origin without inspecting the target iframe URL:

// packages/@tinacms/app/src/lib/preview-origin.ts
// Patched implementation enforcing static origin trust
export const getPreviewOrigin = (): string =>
  typeof window !== 'undefined' ? window.location.origin : '';

In packages/tinacms/src/admin/preview-url.ts, the developer implemented resolvePreviewPath to perform double-pass resolution validation using native URL objects. This prevents protocol-relative bypasses, backslashes, leading tabs, and path traversal tricks:

// packages/tinacms/src/admin/preview-url.ts
export function resolvePreviewPath(
  splat: string | undefined,
  baseOrigin: string = typeof window !== 'undefined' ? window.location.origin : ''
): { path: string; offOrigin: boolean } {
  if (!baseOrigin || !splat) {
    return { path: '/', offOrigin: false };
  }
  try {
    const resolved = new URL(`/${splat}`, baseOrigin);
    if (resolved.origin !== baseOrigin) {
      return { path: '/', offOrigin: true };
    }
    const path = `${resolved.pathname}${resolved.search}${resolved.hash}`;
    // Second pass catches path normalization tricks like ..//
    if (new URL(path, baseOrigin).origin !== baseOrigin) {
      return { path: '/', offOrigin: true };
    }
    return { path, offOrigin: false };
  } catch {
    return { path: '/', offOrigin: true };
  }
}

Exploitation Methodology

Exploitation requires an unauthenticated attacker to distribute a malicious link to an authenticated CMS editor. The link targets the host application's admin route with a protocol-relative URL in the hash parameter.

When the authenticated victim navigates to https://admin.example.com/#/~//attacker.com, the React Router splat parameter captures //attacker.com. The unpatched code sets the iframe src to //attacker.com, forcing the victim's browser to load the attacker's web page inside the TinaCMS admin interface.

The attacker's hosted page sends cross-window messages via window.parent.postMessage(). Because getExpectedPreviewOrigin dynamically adopted https://attacker.com as its expected origin, the parent window's GraphQL message handler accepts the incoming payload and executes arbitrary queries or mutations using the editor's active session context.

Impact & Risk Assessment

CVE-2026-108261 carries a CVSS v3.1 score of 9.3 (Critical) with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N. The primary security scope change occurs because an external cross-origin iframe is granted administrative access to the primary host application's GraphQL communication channel.

Successful exploitation allows the attacker to read, modify, or delete any content managed by the CMS instance. The attacker can execute arbitrary GraphQL mutations to alter site structure, inject malicious code into published posts, or extract confidential operational data.

While the attack requires user interaction (a logged-in editor clicking a link), it requires zero initial privileges on the CMS. No direct system infrastructure denial of service is accomplished through this specific vulnerability.

Remediation Guidance

To eliminate the vulnerability, organizations must update affected npm packages to fixed releases. The patch is available in tinacms version 3.14.0 and @tinacms/app version 2.5.14.

Update dependencies using the appropriate package manager command:

npm install tinacms@3.14.0 @tinacms/app@2.5.14

In addition to updating dependencies, security teams should monitor Web Application Firewall (WAF) or web server access logs for anomalous request patterns in hash fragments, specifically looking for double forward slashes (/#/~//) or backslashes (/#/~/\) within the admin URI paths.

Official Patches

TinaCMSPull request resolving preview origin checking and path resolution logic.
TinaCMSFix commit implementing static window.location.origin checks.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N

Affected Systems

tinacms npm package prior to 3.14.0@tinacms/app npm package prior to 2.5.14

Affected Versions Detail

Product
Affected Versions
Fixed Version
tinacms
TinaCMS
< 3.14.03.14.0
@tinacms/app
TinaCMS
< 2.5.142.5.14
AttributeDetail
CVE IDCVE-2026-108261
CWE IDCWE-346 (Origin Validation Error)
CVSS v3.19.3 (Critical)
Attack VectorNetwork (Requires User Interaction)
ImpactFull Administrative GraphQL Read/Write Access
Exploit StatusProof of Concept / Public Advisory
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1566.002Spearphishing Link
Initial Access
CWE-346
Origin Validation Error

The software does not properly validate that the source of data or communication is valid.

Known Exploits & Detection

GitHub Security AdvisoryTechnical description of preview URL parameter manipulation and origin validation collapse.

References & Sources

  • [1]GHSA-x34j-47hf-4xg7 Security Advisory
  • [2]NVD Vulnerability Detail - CVE-2026-108261
  • [3]CVE.org Record CVE-2026-108261

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-108258
6.9

CVE-2026-108258: Path Traversal in Shiny for Python Bookmark Restoration

A path traversal vulnerability in Shiny for Python (posit-dev/py-shiny) versions 1.4.0 through 1.6.3 allows unauthenticated remote attackers to read arbitrary files and traverse directories via crafted _state_id_ query parameters.

Alon Barad
Alon Barad
0 views•4 min read
•about 2 hours ago•CVE-2026-108260
7.6

CVE-2026-108260: Stored Cross-Site Scripting (XSS) in @tinacms/web-components

A Stored Cross-Site Scripting vulnerability in @tinacms/web-components prior to version 0.2.1 allows low-privileged content authors to execute arbitrary JavaScript code in the context of website visitors via unsanitized URL attributes in custom Markdown rendering components.

Alon Barad
Alon Barad
2 views•5 min read
•about 4 hours ago•CVE-2026-108259
8.2

CVE-2026-108259: Code Injection in @tinacms/cli via Unsanitized Git Branch Name Interpolation

@tinacms/cli prior to version 3.0.0 dynamically constructs client source files using string interpolation without properly sanitizing runtime configuration variables. An attacker with permissions to create a branch or pull request can inject arbitrary JavaScript statements via a crafted Git ref name, leading to execution during automated build processes.

Amit Schendel
Amit Schendel
8 views•5 min read
•about 5 hours ago•CVE-2026-107804
5.3

CVE-2026-107804: Client IP Resolution Flaw & Authentication Lockout in Nginx UI

Nginx UI versions 2.2.0 through 2.5.10 fail to properly configure Gin framework trusted proxies when deployed behind a reverse proxy. This causes all incoming HTTP requests to be attributed to the loopback IP (127.0.0.1), enabling IP allowlist bypass and global authentication lockouts.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 6 hours ago•CVE-2026-107805
7.5

CVE-2026-107805: Unauthenticated Storage Exhaustion in Nginx UI Node Authentication

Nginx UI versions 2.5.0 through 2.5.10 contain an uncontrolled resource consumption vulnerability in the node authentication handler. Unauthenticated remote attackers can exhaust host disk storage and I/O resources by submitting large HTTP request bodies to node-signature endpoints prior to cryptographic signature validation.

Alon Barad
Alon Barad
4 views•6 min read
•about 7 hours ago•GHSA-4HV6-XC92-J86G
6.5

GHSA-4HV6-XC92-J86G: Insufficient Session Expiration in Vikunja WebSocket Authentication Pipeline

Vikunja versions 2.3.0 through 2.6.0 contain an insufficient session expiration vulnerability (CWE-613) within the WebSocket authentication handler. Although Vikunja enforces server-side session tracking and revocation for REST API routes, the WebSocket handshake handler validates cryptographic JWT signatures without querying the database session state. Consequently, revoked JWT tokens can establish new real-time WebSocket connections, and existing connections persist after session revocation.

Alon Barad
Alon Barad
5 views•5 min read