Strona główna / Blog / Grav: jedno CVE, dwa błędy

Blog · analiza

Grav CVE-2026-112780 i 112779: vendor mówi High i Moderate, VulnCheck 9.3. Jedno CVE, dwa błędy i wektor sklejony z najgorszych części obu

19 października 2026 o 20:17 UTC, w tej samej partii co osiem CVE dla Craft CMS, VulnCheck nadał dwa identyfikatory projektowi Grav: CVE-2026-112780 dla silnika i CVE-2026-112779 dla wtyczki API. To nie są nowe błędy. Grav opisał je w GitHub Security Advisories 4 i 5 października, a poprawki wydał 28 września. Mechanizm „vendor ocenia skromniej, CNA daje 9.3” opisywałem już przy Craft CMS. Grav dokłada dwie rzeczy, których tam nie było: jeden rekord CVE obejmuje dwa różne błędy, a wektor bierze z każdego najgorszą część. W drugim rekordzie CVSS 4.0 i CVSS 3.1 od tej samej CNA nie zgadzają się co do tego, czy atakujący potrzebuje konta.

Produkt: Grav, płaski CMS w PHP (pakiet Composer getgrav/grav) i jego wtyczka API (getgrav/grav-plugin-api).
CVE: CVE-2026-112780 i CVE-2026-112779, CNA disclosure@vulncheck.com, w NVD od 19.10.2026 20:17 UTC, status „Deferred” (NVD nie doda własnej oceny). W GitHub Advisory Database jako nowe wpisy „unreviewed” z oceną „critical”.
Ocena vendora: GHSA-9rq7-4cch-f22j „High”, GHSA-8pcm-97fc-4xwh „Moderate”. Bez liczb CVSS i bez numerów CVE w advisory.
Poprawki: Grav 2.2.2 i grav-plugin-api 1.0.42, obie z 28.09.2026. Bieżące wersje: Grav 2.2.11 (19.10), grav-plugin-api 1.0.55 (22.10).
Threat state: brak w CISA KEV (katalog 2026.10.21, sprawdzony 22.10.2026). CISA-ADP SSVC dla 112779: exploitation: none, automatable: yes. EPSS ok. 0,003 dla obu. Nie znalazłem informacji o wykorzystaniu ani publicznego PoC.

Dwa rekordy, dwie skale

CVE / GHSA vendoraProblem (wg GHSA)WersjeVendorVulnCheck CVSS 4.0VulnCheck CVSS 3.1
CVE-2026-112780
GHSA-9rq7-4cch-f22j
Redaktor stron obchodzi allowlistę wywołań w formularzu Flex przez replace-name@ i wywołuje dowolne publiczne metody statyczne (usuwanie katalogów, przenoszenie i nadpisywanie plików, odczyt plików)Grav 2.0.15 – 2.2.1, fix 2.2.2. Gałąź 1.7 niepodatnaHigh9.3 · PR:N · VC:H/VI:H/VA:H8.8 · PR:L
CVE-2026-112779
GHSA-8pcm-97fc-4xwh
(a) Anonimowe żądania do GET /api/v1/translations/{lang} zapełniają cache (ok. 560 KB na żądanie <100 B). (b) Konto z api.pages.write omija reguły stron w sync i batch copygrav-plugin-api: (a) 1.0.40 – 1.0.41, (b) 1.0.16 – 1.0.41, fix 1.0.42Moderate9.3 · PR:N · VC:H/VI:H/VA:H9.8 · PR:N · C:H/I:H/A:H

Oś czasu jest taka sama jak przy Craft: poprawka 28.09, advisory vendora bez CVE 4–5.10, CVE od zewnętrznej CNA 19.10. Narzędzie kluczujące po CVE do 19.10 nie miało czego dopasować, a od 19.10 widzi „Critical 9.3” dla błędów poprawionych trzy tygodnie wcześniej. Szkic VMRT Radar opisywał to jako rozbieżność ocen „w bazie niezweryfikowanych advisory”. Precyzyjniej: liczby pochodzą od VulnCheck jako CNA i to one trafiają do NVD oraz, stamtąd, do skanerów.

CVE-2026-112780: rekord, który przeczy sam sobie

Advisory vendora mówi jasno, kto może wykorzystać błąd: „An account with page-edit permission (api.pages.write, or admin.pages in the classic admin)”. Opis CVE od VulnCheck powtarza to samo: „Attackers with page-edit permission”. Mimo to w tym samym rekordzie:

  • CVSS 3.1 (oznaczony w NVD jako Primary): PR:L, wynik 8.8.
  • CVSS 4.0 (Secondary): PR:N, wynik 9.3.

Ten sam CVSS 4.0 z PR:L daje 8.7, czyli pasmo High, zgodne z oceną vendora. Różnica między 8.7 a 9.3 przebiega przez granicę High/Critical i w wielu politykach VM oznacza inne SLA. Przy Craft CMS VulnCheck popełnił odwrotny błąd w dwóch rekordach (PR:L lub PR:N w v4.0, PR:H w v3.1). Wzorzec się powtarza: w rekordach z tej partii wektory 4.0 i 3.1 nie zawsze opisują ten sam scenariusz. Jeśli Twój skaner bierze „najnowszą wersję CVSS”, dostanie 9.3. Jeśli bierze ocenę „Primary”, dostanie 8.8.

Do rejestru wziąłbym 8.7 (CVSS 4.0, PR:L) z uzasadnieniem w postaci cytatu z advisory. Kontekst ma tu znaczenie: atak wymaga konta redaktora, ale skutek (usuwanie katalogów, nadpisywanie plików, odczyt plików poza drzewem stron) wykracza daleko poza rolę redaktora. Na witrynie z wieloma redaktorami albo z kontami API dla integracji to realne przejęcie serwera przez kogoś, kto miał tylko edytować treść. Gałąź 1.7 według vendora nie jest podatna, bo tam allowlistę stosowano do każdej dyrektywy.

CVE-2026-112779: dwa błędy w jednym rekordzie

GHSA-8pcm-97fc-4xwh opisuje dwa niezależne problemy wtyczki API z różnymi warunkami i różnymi zakresami wersji. VulnCheck zrobił z nich jedno CVE i jeden wektor. Rozpisane osobno wyglądają tak:

Część CVE-2026-112779Kto możeSkutek wg GHSAWektor CVSS 4.0 (moja propozycja)Wynik
(a) cache tłumaczeńKażdy, bez kontaWyczerpanie dysku lub APCu, niedostępność stronyAV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N8.7 (CVSS 3.1: 7.5)
(b) sync i batch copyKonto z api.pages.writeNadpisanie tłumaczenia lub utworzenie strony wbrew regułom na poziomie stronyAV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N5.3 (CVSS 3.1: 4.3)
Rekord VulnCheck (całość)PR:NVC:H/VI:H/VA:HAV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N9.3 (CVSS 3.1: 9.8)

Wektor z rekordu bierze PR:N z części (a) i pełne VC:H/VI:H/VA:H, którego nie uzasadnia żadna z części. Anonimowy atakujący może tylko zapełnić cache, czyli wpłynąć na dostępność. Zapisy wbrew regułom stron wymagają konta z api.pages.write. Utraty poufności advisory nie opisuje wcale. Wprost wyłącza nawet odczyt źródła strony przez compare („Reading page source is within api.pages.read, so that is not part of this advisory”). Wyniki w tabeli policzyłem sam według algorytmu referencyjnego FIRST. Wektory są moją propozycją, nie oceną vendora ani CNA. Wyszło 8.7 dla części anonimowej i 5.3 dla części z kontem, a nie 9.3 dla całości. CVSS 3.1 z rekordu (9.8) jest jeszcze dalej od opisu.

Ciekawszy jest zakres wersji. Część anonimowa dotyczy tylko grav-plugin-api 1.0.40 i 1.0.41. Według GitHub Releases 1.0.40 wyszła 24.09, 1.0.41 25.09, a poprawka 1.0.42 już 28.09. Podatna na anonimowy DoS wersja była więc najnowsza przez około cztery dni. Rekord CVE podaje jeden zakres, „1.0.16 before 1.0.42”. Instalacja na 1.0.30 trafi w skanerze do kategorii 9.3 z PR:N, choć anonimowej części błędu w ogóle nie ma i grozi jej tylko problem wymagający konta.

To nie pierwszy przypadek „jednego CVE na kilka luk”. Cisco robi to celowo, grupując podatności według CWE, co opisywałem w tekście Jedno CVE, wiele różnych luk. Tutaj grupowanie wynika z tego, że CNA nadała jeden identyfikator jednemu advisory. Skutek dla VM jest taki sam: jedno CVE nie jest jednym findingiem.

Jak to rozpisać w VM

  1. Przechowuj ocenę vendora i CNA osobno. Vendor: High i Moderate. CNA: 9.3 i 9.3. Przy rozbieżności zapisz, którą przyjmujesz i dlaczego, z cytatem z advisory.
  2. Rozbij CVE-2026-112779 na dwa findingi: „anonimowy DoS cache” tylko dla 1.0.40 i 1.0.41, „obejście reguł stron” dla 1.0.16–1.0.41. Każdy z własnym priorytetem i własnym warunkiem (czy endpoint API jest publiczny, kto ma api.pages.write).
  3. CVE-2026-112780 oceniaj przez role: ilu ludzi i ile integracji ma prawo edycji stron. Jeśli tylko administratorzy, realne ryzyko jest niskie. Jeśli redaktorzy z zewnątrz albo tokeny API w systemach trzecich, to droga do plików serwera.
  4. Inwentarz: rekordy nie mają CPE (status Deferred), więc dopasowanie po CPE nic nie da. Wersję Grav i wtyczek bierz z composer.lock albo z katalogu user/plugins, i sprawdzaj osobno silnik i wtyczkę API. To dwa różne komponenty z różnymi poprawkami.
  5. SLA licz od 28.09, nie od 19.10. Kto aktualizuje Grav na bieżąco, ma obie poprawki od trzech tygodni. Cel ticketu: bieżące wersje (Grav 2.2.11, grav-plugin-api 1.0.55 lub nowsze), nie minimalne 2.2.2 i 1.0.42.
  6. Po aktualizacji: przegląd logów operacji plikowych i zmian stron z okresu ekspozycji, jeśli instancja ma redaktorów spoza zespołu, oraz rozmiaru katalogu cache dla wersji 1.0.40–1.0.41.

Powiązane na blogu

Źródła

  • Grav — GHSA-9rq7-4cch-f22j „Page editor can call arbitrary static methods through a renamed field in a Flex form” (High, 5.10.2026) — github.com
  • Grav — GHSA-8pcm-97fc-4xwh „API plugin: anonymous translation requests grow the cache without limit, and translation sync and batch copy skip page rules” (Moderate, 4.10.2026) — github.com
  • NVD — CVE-2026-112780 (CNA VulnCheck, CVSS 4.0 9.3 / CVSS 3.1 8.8, status Deferred) — nvd.nist.gov
  • NVD — CVE-2026-112779 (CNA VulnCheck, CVSS 4.0 9.3 / CVSS 3.1 9.8, SSVC CISA-ADP, status Deferred) — nvd.nist.gov
  • Grav — wydania (2.2.2 z 28.09.2026, 2.2.11 z 19.10.2026) — github.com
  • grav-plugin-api — wydania (1.0.40, 1.0.41, 1.0.42, 1.0.55) — github.com
  • FIRST — CVSS v4.0 Specification — first.org
  • CISA Known Exploited Vulnerabilities Catalog (brak wpisów Grav w wersji 2026.10.21) — cisa.gov

Nota redakcyjna: wpis powstał na podstawie szkicu VMRT Radar z 20 października 2026 i został zweryfikowany ze źródłami pierwotnymi 20 października 2026, a rekordy NVD i katalog CISA KEV sprawdziłem ponownie 22 października 2026 (KEV w wersji 2026.10.21, bez wpisów Grav; NVD bez zmian, status Deferred). Źródła: advisory GHSA-9rq7-4cch-f22j i GHSA-8pcm-97fc-4xwh w repozytorium getgrav/grav (przez GitHub API: poziom, daty, zakresy wersji, CWE, brak CVSS i CVE), rekordy NVD API 2.0 dla CVE-2026-112780 i CVE-2026-112779, wpisy GitHub Advisory Database, daty wydań Grav i grav-plugin-api z GitHub Releases oraz API EPSS. Względem szkicu wskazałem VulnCheck jako źródło ocen 9.3, opisałem sprzeczność CVSS 4.0 i 3.1 w rekordzie 112780 i podałem daty poprawek (28.09.2026). Alternatywne wektory i wyniki (8.7, 8.7, 5.3) to moja ocena, policzona algorytmem referencyjnym FIRST, a nie ocena vendora ani CNA. Nie potwierdziłem: wykorzystania ani PoC, treści advisory VulnCheck, udziału instalacji z wtyczką API ani tego, czy panel administracyjny Grav 2.x domyślnie z niej korzysta.

Zapamiętaj jedno

Grav dostał od VulnCheck dwa CVE z oceną 9.3 za błędy, które vendor ocenił jako High i Moderate i poprawił 28 września. W CVE-2026-112780 ten sam rekord ma PR:N w CVSS 4.0 i PR:L w CVSS 3.1, a advisory wymaga konta redaktora. Uczciwy wynik to 8.7. CVE-2026-112779 łączy anonimowy DoS cache, który istniał tylko w dwóch wersjach wtyczki dostępnych przez cztery dni, z obejściem reguł stron dla konta z prawem zapisu. Wektor rekordu bierze z obu części najgorsze elementy. Rozpisane osobno dają 8.7 i 5.3. Jedno CVE to tu dwa findingi, a SLA liczysz od daty poprawki.