Przejdź do treści
Wszystkie projekty

03Portfolio

WireMark — bezpieczny język znaczników

Rozszerzony Markdown do bezpiecznego formatowania komentarzy i opisów pisanych przez użytkowników. Biblioteka w TypeScript nie ma zewnętrznych pakietów i przepuszcza tylko to, co jest wprost dozwolone. Ma też integrację z NestJS i edytor wizualny.

W liczbach

Rodzaje elementów
24
Zewnętrzne pakiety w bibliotece
0
Maksymalna długość tekstu (znaki)
100 000
01

Problem

Komentarze, opisy i posty użytkowników potrzebują czegoś więcej niż zwykły tekst: nagłówków, list, kodu, wyróżnień. Każde takie pole otwiera jednak drogę do ataku XSS, czyli podrzucenia kodu, który wykona się w przeglądarce innych osób: skryptu w treści, linku javascript:, obrazka z doklejonym skryptem albo niewidocznych znaków odwracających kierunek tekstu. Przy filtrowaniu gotowego HTML-a łatwo przeoczyć jeden z tych przypadków.

02

Podejście

WireMark w ogóle nie przyjmuje HTML-a, więc nie musi go czyścić. Tekst najpierw przechodzi kontrolę: limit 100 000 znaków, ujednolicenie zapisu znaków i usunięcie niewidocznych znaków sterujących. Potem biblioteka rozpoznaje 24 rodzaje elementów i tylko z nich buduje HTML. Znaki specjalne zamienia na bezpieczne odpowiedniki. Linki przechodzą tylko z protokołem https, http albo mailto (opcjonalnie tylko z wybranych domen), obrazki tylko przez https, a kolory, rodzaje ramek, języki kodu i emoji mają własne listy dozwolonych wartości. Obok HTML-a biblioteka zwraca dziennik tego, co odrzuciła, i sygnał, że treść wygląda podejrzanie, a osobna funkcja sprawdza tekst przed zapisem. Do NestJS jest gotowy moduł, który podpina to wszystko w aplikacji.

03

Efekt

Gotowa jest biblioteka (ok. 970 linii TypeScript, bez zewnętrznych pakietów), integracja z NestJS i dwie strony w czystym HTML i JS. Pierwsza to demo z edytorem i podglądem na żywo, druga to edytor wizualny z menu komend pod „/”, pływającym paskiem formatowania, spisem treści i eksportem do HTML, WireMark albo czystego tekstu. W demo wklejony skrypt, obrazek z doklejonym skryptem i link javascript: wyświetlają się jako zwykły tekst albo są blokowane, a osobny pasek pokazuje, co odrzucono.

Jak to działa

  1. 01

    Najpierw kontrola, potem formatowanie

    Zanim cokolwiek zostanie przetworzone, tekst jest przycinany do limitu długości, ujednolicany i czyszczony z niewidocznych znaków sterujących, bajtów zerowych i mieszanych końców linii.

  2. 02

    Tylko to, co dozwolone

    Link przechodzi tylko z https, http albo mailto (i opcjonalnie tylko z dozwolonej domeny), obrazek tylko przez https. Nieznany kolor odznaki zamienia się w szary, nieznany rodzaj ramki w domyślny, a nazwa języka w bloku kodu zostaje obcięta do liter, cyfr, myślnika i podkreślnika.

  3. 03

    Wstrzyknięcie zostaje tekstem

    Znaki specjalne są zamieniane na bezpieczne odpowiedniki, więc wklejony <script> albo obrazek z doklejonym skryptem wyświetlają się jako zwykły tekst i nic się nie wykonuje. Linki javascript: są odrzucane, a każde takie zdarzenie trafia do dziennika.

    Wstrzyknięcie zostaje tekstem
  4. 04

    Rozszerzona składnia

    Oprócz zwykłego Markdownu: ramki z uwagami różnego rodzaju, kolorowe odznaki, ukryte spoilery, zaznaczenie, indeks górny i dolny, emoji po nazwie z zamkniętej listy oraz bloki kodu z przyciskiem kopiowania.

    Rozszerzona składnia
  5. 05

    Gotowe do NestJS

    Gotowy moduł do aplikacji w NestJS. Treść wysłana do aplikacji może trafiać do kodu od razu jako bezpieczny HTML, a gdy trzeba, tekst da się też przetworzyć ręcznie.

Napisz