pacioli: Znacznik zgody na zatwierdzenie zezwalał na anulowanie istniejących dokumentów wskazanych przez wywołującego
Komunikat źródłowy zmienił się od przygotowania tego objaśnienia. Sprawdź aktualne dane techniczne i oryginalny komunikat poniżej.
Wpływ
Bramka zgody na poziomie dokumentów w pacioli-guard wymaga utworzonego przez człowieka, jednorazowego, powiązanego z dokumentem oraz powiązanego z czynnością znacznika, zanim poświadczenie z uprawnieniem API Key Scope.require_consent będzie mogło zatwierdzić lub anulować dokument. Ponieważ ERPNext wykonuje dalsze operacje zapisu dokumentów w następstwie kontrolowanej czynności, czynności zagnieżdżone mogą skorzystać z uprawnień (ride) zgody ustanowionej przez czynność nadrzędną, zamiast wymagać własnego znacznika.
Predykat przejęcia zgody zwracał true dla każdego anulowania, niezależnie od tego, na jaką czynność zezwalał znacznik nadrzędny. Przejęcie zgody nigdy nie dociera do consent_verdict, gdzie wymuszane jest powiązanie znacznika z czynnością. W rezultacie każda operacja Document.cancel() wykonana wewnątrz czynności z ustaloną zgodą docierała do docstatus = 2 bez znacznika, bez weryfikacji powiązania czynności, bez jednorazowego zużycia i bez wpisu audytowego o odmowie.
Ścieżka ta jest dostępna przy dokładnie takim zestawie uprawnień, jaki zgodnie z dokumentacją operator nadaje brokerowi, a tożsamość anulowanego dokumentu jest kontrolowana przez wywołującego:
Sales Invoice.on_submit(sales_invoice.py:507) bezwarunkowo wywołujeprocess_asset_depreciation(), dochodząc dodepreciate_asset_on_sale(:1508-1516).- Następnie iteruje po wierszach pozycji faktury i wywołuje
frappe.get_doc("Asset", d.asset). PoleSales Invoice Item.assetjest zwykłym zapisywalnymLinkbezread_onlyorazfetch_from, więc wywołujący przekazuje je w treści żądania. Walidacja, która mogłaby je ograniczyć, znajduje się zaif d.is_fixed_asset:(:428-429), polem ustawianym przez serwer. - Łańcuch dociera do
depreciation.py:481, a następnie doasset_depreciation_schedule.py:215-217, co wywołujecurrent_schedule.cancel()nadocstatus == 1, zatwierdzalnymAsset Depreciation Schedulepoprzez cykl życia dokumentu (ustawione jest tylkoshould_not_cancel_depreciation_entries, a nieignore_validate, w związku z czymbefore_canceljest wywoływane i to przejęcie zgody umożliwiło wykonanie operacji).
W ten sposób jeden znacznik autoryzujący submit Sales Invoice X anulował zatwierdzony dokument, którego człowiek nigdy nie widział ani nie zatwierdził. Anulowanie takiego dokumentu cofa jego skutki w księdze głównej.
Taki sam schemat występuje przy szerszych uprawnieniach, na przykład Unreconcile Payment.on_submit (unreconcile_payment.py:59-64), który iteruje po tabeli podrzędnej wypełnianej przez wywołującego i osiąga accounts/utils.py:857/:859 gain_loss_je.cancel() na zatwierdzonych wpisach do księgi (Journal Entries).
Kogo dotyczy problem
Problem dotyczy wyłącznie instancji, które włączyły bramkowanie zgód: poświadczenie musi posiadać API Key Scope z ustawionym require_consent. Mechanizm pacioli-guard jest nieaktywny dla podmiotów bez takiego uprawnienia, a bazowy zakres poświadczeń (auth_hooks) pozostaje nienaruszony.
Bramka zgody na poziomie dokumentu została po raz pierwszy opublikowana w 0.9.6, co stanowi jedyną wydaną wersję w podatnym zakresie.
Ryzyko rezydualne
W ramach kontrolowanego anulowania kaskadowe anulowanie wcześniej istniejącego dokumentu nadal korzysta z przejętej zgody. Jest to kluczowe dla operacji cofania (zwykłe anulowanie faktury powoduje, że ERPNext anuluje powiązane noty kredytowe/debetowe i wpisy księgowe za pośrednictwem accounts_controller.py:2001-2005) i nie może zostać zawężone bez sygnału, że kaskadowe anulowanie jest bezpośrednią konsekwencją dokumentu nadrzędnego. Uzasadnienie to nie obejmuje jednak wszystkich dopuszczanych przypadków: co najmniej jeden z nich może być kontrolowany przez wywołującego w taki sam sposób jak omawiana podatność: Asset Repair.on_cancel (asset_repair.py:215-222), który anuluje Serial and Batch Bundle wskazany przez powiązanie (Link) uzupełniane w tabeli podrzędnej. pacioli-guard nie obejmuje również operacji zapisu ustawiających flags.ignore_validate ani takich, które całkowicie pomijają cykl życia dokumentu (bezpośredni SQL, zapisy pól przez db_update/db_set); te ograniczenia są opisane w dokumentacji projektu i pozostają niezmienione.
Podziękowania
Podatność wykryta podczas wewnętrznego przeglądu bezpieczeństwa w dniu 2026-07-28, który przeanalizował predykat w kodzie źródłowym frappe 16.28.0 i ERPNext v16, a nie tylko w dokumentacji projektu. Poprzedni komentarz w kodzie zakładał brak takich mechanizmów, co sformułowano bez wcześniejszej analizy źródeł.
Co trzeba zrobić
Poprawki
Problem naprawiono w 0.10.0. Mechanizm przejęcia zgody rozróżnia teraz czynność nadrzędną: operacja cofania może kaskadowo wywołać kolejne cofnięcia, ale operacja zatwierdzenia (submit) nie może kaskadowo wywołać anulowania dokumentu posiadającego już nazwę, ponieważ jest to czynność, o zatwierdzenie której można było poprosić człowieka. Znacznik nadzoru przechowuje teraz czynność, dla której został ustanowiony, zamiast prostej wartości logicznej.
Aktualizacja zmienia zachowanie systemu. Każdy przepływ ERPNext, w którym zatwierdzenie prowadzi kaskadowo do anulowania w cyklu życia, wymaga teraz znacznika zgody na to anulowanie oprócz znacznika na samą czynność. W ERPNext v16 obejmuje to sprzedaż środków trwałych, sprzedaż częściowej ilości środków trwałych, notę kredytową do sprzedaży środka trwałego, kapitalizację naprawy środka trwałego, alokację zmianową środka trwałego, korektę wartości środka trwałego oraz Unreconcile Payment. Aby to umożliwić, nagłówek X-Pacioli-Consent akceptuje teraz wiele znaczników rozdzielonych spacjami lub przecinkami; każdy pozostaje powiązany z jednym dokumentem i jedną czynnością, wymaga innego wystawcy i jest zużywany dokładnie raz.
Obejścia
W wersji 0.9.6 należy usunąć require_consent z uprawnień i polegać wyłącznie na bazowych ograniczeniach poświadczeń lub ograniczyć nadzorowane poświadczenia, aby nie mogły zatwierdzać dokumentów, których kontrolery anulują inne dokumenty (dla ERPNext slice-one znaną ścieżką jest Sales Invoice z wypełnionym powiązaniem asset w wierszu pozycji). Żadne z tych obejść nie zastępuje aktualizacji.
Czego dotyczy
Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.
| Platforma | Paczka | Podatne wersje | Poprawka w wersji |
|---|---|---|---|
| Python (PyPI) | pacioli-guard | >= 0.9.6, < 0.10.0 | 0.10.0 |
Odnośniki
- https://github.com/john-broadway/pacioli/security/advisories/GHSA-3hj7-6vmj-h8v4
- https://nvd.nist.gov/vuln/detail/CVE-2026-107841
- https://github.com/john-broadway/pacioli/commit/f3c7219f5dde6050bd7921e0ac55afd02771250c
- https://github.com/john-broadway/pacioli
- https://github.com/john-broadway/pacioli/releases/tag/guard-v0.10.0
- https://pypi.org/project/pacioli-guard
- https://github.com/advisories/GHSA-3hj7-6vmj-h8v4
- Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:N- Słabość (CWE)
CWE-863- Platforma
- Python (PyPI)
- Paczka
pacioli-guard- Ujawniono
- 09.10.2026
- Aktualizacja
- 15.10.2026 18:17
Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.
OSV / GitHub Advisory Database - PYSEC-2026-4246 - PyPA Advisory Database; CC BY 4.0
OSV / GitHub Advisory Database - GHSA-3hj7-6vmj-h8v4 - CC BY 4.0
Historia podatności: pacioli-guard
Wszystkie opisane podatności tej paczki (Python (PyPI)), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.
To jedyna znana podatność tej paczki.
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.