Niezależnie od tego, czy to twoja organizacja tworzy oprogramowanie, czy tylko jest jego użytkownikiem, jest prawdopodobnie narażona na ryzyko związane z błędami ukrytymi głęboko w kodzie.
Jednym z kluczowych sposobów zwiększania wydajności przy tworzeniu oprogramowania jest korzystanie z bibliotek podczas tworzenia własnych produktów i usług. Pomaga to przyspieszyć innowacje cyfrowe, ale wiąże się z kompromisem: organizacje akceptują, czasami nieświadomie, pewien stopień ryzyka, który może prowadzić do poważnych problemów z cyberbezpieczeństwem. Takie ryzyko ujawniło się w grudniu 2021 roku, kiedy wyszło na jaw, że szeroko stosowany framework oprogramowania open source o nazwie Log4j zawiera krytyczną lukę. Wiadomość ta trafiła na pierwsze strony gazet, ponieważ olbrzymia ilość oprogramowania wdrożonego w organizacjach, agencjach rządowych oraz na komputerach prywatnych używa tego kodu w języku Java do logowania. Eksperci bezpieczeństwa odkryli, że exploity oparte na luce w Log4Shell, jak ją nazwano, mogą mieć katastrofalne skutki dla firm i osób prywatnych. Okazało się, że podatność na tę lukę jest niezwykle rozległa. Kod został wbudowany w wiele systemów, wprowadzając krytyczną lukę w oprogramowaniu na całym świecie. Ujawnienie Log4j powinno być sygnałem ostrzegawczym dla kadry kierowniczej aby lepiej przemyślała ponowne wykorzystanie oprogramowania oraz sposoby ograniczania ryzyka związanego z jego używaniem w swoich organizacjach.
Korzystanie z bibliotek oprogramowania powstało jako środek zwiększający wydajność w dużych firmach programistycznych i było głównie przedsięwzięciem wewnętrznym, obejmującym komponenty tworzone własnymi siłami. Pojawienie się internetu i eksplozja oprogramowania typu open source zmieniły tę praktykę. Obecnie większość oprogramowania jest przynajmniej częściowo zbudowana na funkcjonalności uzyskanej dzięki zewnętrznym komponentom. Komponenty te są często udostępniane dla wszystkich na repozytoriach open source, takich jak PyPI dla Pythona, NPM dla Node.js czy Centralne Repozytorium Mavena dla Javy, by wymienić tylko kilka.
Główną zaletą dla programistów używających komponentów z tych repozytoriów jest to, że nie muszą przejmować własności kodu ani brać odpowiedzialności za poprawki błędów lub rozszerzenia funkcji. Mogą skupić się na tworzeniu własnych aplikacji, korzystając jednocześnie z pracy innych. Ponadto łatwiej jest zaimportować cały pakiet, niż wybierać konkretne wiersze kodu, które zwykle trzeba potem zmodyfikować, aby pasowały do własnego kodu źródłowego. Pakiet jest zamknięty i zbudowany jako gotowe rozwiązanie do ponownego użycia, które może być traktowane przez programistów jak czarna skrzynka. Ręczne wybieranie konkretnych linii kodu oznacza konieczność przedzierania się przez kod źródłowy pakietu i identyfikowania, kopiowania lub powielania jego fragmentów, co jest bardziej czasochłonne.
Inwentaryzacja ponownego wykorzystania
Liderom biznesowym może być trudno zrozumieć, w jakim stopniu ponowne wykorzystanie jest zakorzenione w praktykach tworzenia oprogramowania. Aby zilustrować jego wszechobecność, weźmy pod uwagę, że Lodash, jeden z najpopularniejszych pakietów JavaScript typu open source dostępnych w repozytorium NPM, został w 2021 roku pobrany ponad 2 miliardy razy (czyli średnio ponad 40 milionów razy tygodniowo) i że ponad 149 tys. innych pakietów opublikowanych na NPM jest od niego zależnych. Chalk, inny popularny pakiet, został pobrany w 2021 roku ponad 5 miliardów razy i zależy od niego ponad 77 tysięcy innych pakietów opublikowanych w NPM. Niektórzy badacze twierdzą, że pisanie oprogramowania polega obecnie bardziej na tworzeniu „kodu klejowego” („glue code”), łączącego fragmenty komponentów oprogramowania, niż na pisaniu zupełnie nowych zestawów instrukcji lub algorytmów.
Autorzy niedawno przeprowadzonego badania na temat tej praktyki zauważyli, że „przemysł programistyczny przechodzi zmianę paradygmatu. W przeciwieństwie do przeszłości, kiedy ponowne wykorzystanie oprogramowania było anomalią, obecnie dla wszystkich znaczących projektów rozwoju oprogramowania staje się ono normą” – ten pogląd podziela wiele osób.
Aby uzmysłowić sobie skalę tego zjawiska, należy wziąć pod uwagę, że w przypadku każdego komponentu oprogramowania, który zespół decyduje się ponownie wykorzystać, istnieje duże prawdopodobieństwo, że dany fragment zależy od innych komponentów oprogramowania, które również mają swoje własne zależności. (Zob ilustracja poniżej: Zależności ponownego wykorzystania oprogramowania w zasadzie i w praktyce).
ZALEŻNOŚCI ZWIĄZANE Z PONOWNYM UŻYCIEM OPROGRAMOWANIA. ZASADY I PRAKTYKA
Diagram po lewej stronie ilustruje bezpośrednie i pośrednie zależności tworzone przez ponowne wykorzystanie oprogramowania; diagram po prawej stronie pokazuje rzeczywisty przykład zakresu takiej sieci zależności dla frameworka Express. Express zależy bezpośrednio od 48 innych pakietów, które z kolei zależą od łącznie 250 dodatkowych pakietów

Oznacza to, że kiedy programista importuje jeden komponent – w tym kontekście nazywany również zależnością – w tym samym czasie mogą zostać wprowadzone dziesiątki innych zależności, które są zawarte w tym jednym komponencie, coś na zasadzie matrioszki. W rezultacie duży projekt oprogramowania może pośrednio zależeć od tysięcy innych fragmentów tworzonych i utrzymywanych przez tyle samo zespołów programistów, z których każdy ma swoje własne interesy, cele i plany. W przypadku Log4j jego twórcy szybko zareagowali na ujawnioną lukę, a jego nowa wersja została udostępniona do pobrania w ciągu kilku dni. Jest to dowód szybkiego działania społeczności open‑source w przypadku pojawienia się problemów. Jednak prawdziwym wyzwaniem dla wielu tysięcy organizacji było to, że wszyscy ci, którzy używali podatnej wersji Log4j w swoim oprogramowaniu, stali się odpowiedzialni za aktualizację i zarządzanie rozwiązywaniem incydentów swoich klientów. Chociaż Log4Shell jest bez wątpienia skrajną ilustracją tego zjawiska, często pojawiają się doniesienia o odkryciu błędów w popularnych pakietach lub problemów wynikających z używania pakietów niskiej jakości lub przestarzałych do produkcji własnego oprogramowania. W niektórych przypadkach okazuje się, że problemy te dotyczą milionów urządzeń, których nie da się łatwo zaktualizować. Pomimo niepożądanych skutków organizacje mogą tak wiele zyskać dzięki ponownemu wykorzystaniu, że będzie ono odgrywać coraz większą rolę w praktyce tworzenia oprogramowania. Jednocześnie liderzy biznesowi powinni być świadomi konsekwencji takiego postępowania, nawet jeśli nie zajmują się tworzeniem oprogramowania. Oto cztery kluczowe spostrzeżenia dla liderów, którzy zastanawiają się nad sposobami zarządzania ryzykiem w swoich organizacjach:
Zastanów się nad konsekwencjami
Ponowne wykorzystanie oprogramowania może w krótkim czasie zwiększyć wydajność, ale może mieć też konsekwencje długoterminowe. Na przykład, jeśli w zewnętrznym komponencie wystąpi błąd, organizacja będzie musiała poczekać z ponownym wdrożeniem własnego oprogramowania do czasu jego usunięcia. Niektóre projekty open source korzystają z zaangażowanej, aktywnej społeczności programistów, tak jak to jest w przypadku Log4j. Możliwe jest jednak również, że społeczność wspierająca rozwój straci zainteresowanie. Kluczowi programiści mogą odejść do innych projektów. Jeśli rozwój jakiegoś konkretnego elementu kodu zostanie zatrzymany, programiści mogą być zmuszeni do pracy z przestarzałym pakietem.
Oceniając przydatność komponentu do ponownego użycia, zespół programistów powinien brać pod uwagę nie tylko bezpośrednie potrzeby funkcjonalne. Powinien on przeprowadzić analizę społeczności lub organizacji (w tym swojej własnej) wspierającej projekt, jej reakcji na błędy lub prośby o nowe funkcje oraz ogólnych osiągnięć, aby określić, czy twoja organizacja będzie mogła nadal liczyć na ten komponent w przyszłości.
Obecnie większość oprogramowania jest przynajmniej częściowo zbudowana na funkcjonalności uzyskanej dzięki zewnętrznym komponentom.
Spójrz poza bezpośrednie zależności
Jeśli domyślną praktyką w twojej organizacji jest systematyczne poszukiwanie oprogramowania wielokrotnego użytku w celu implementacji funkcjonalności, prawdopodobnie twoje oprogramowanie jest zależne od setek, jeśli nie tysięcy, komponentów zewnętrznych. Ważne jest, aby spojrzeć poza bezpośrednie zależności i ocenić zależności pośrednie, które są konsekwencją danej decyzji o ponownym wykorzystaniu.
W niektórych przypadkach warto podjąć ryzyko związane z przejęciem pakietów, ponieważ uzyskana w ten sposób funkcjonalność pomoże w osiągnięciu celów projektu. Czasami jednak pojedyncza funkcjonalność zależy od dziesiątek innych komponentów zewnętrznych. W takich przypadkach najlepszym rozwiązaniem może być ponowne zaimplementowanie tej części funkcjonalności, którą chcemy pozyskać, a w razie potrzeby wybranie kilku wybranych komponentów zewnętrznych, które pomogą nam w drodze. Chociaż może to wymagać więcej pracy na początku i może sprawiać wrażenie ponownego wymyślania koła, czasami jest to najrozsądniejsza decyzja, zarówno z biznesowego, jak i technicznego punktu widzenia. Proces podejmowania decyzji w organizacji o ponownym wykorzystaniu powinien obejmować staranną ocenę zapotrzebowania na konkretną funkcjonalność w świetle pośrednich zależności, jakie ona ze sobą niesie.
Okresowo przeglądaj używane komponenty
Decyzje o włączeniu do oprogramowania komponentów zewnętrznych powinny być regularnie weryfikowane w ramach dobrej praktyki spłacania długu technicznego (definiowanego jako koszt wcześniejszych decyzji o wyborze rozwiązania korzystnego zamiast najlepszego). Zespoły programistów są często zachęcane do angażowania się w refaktoryzację, czyli praktykę, w której kod źródłowy jest reorganizowany w celu zredukowania długu technicznego nagromadzonego w postaci wcześniejszych skrótów i obejść kodowych, tak aby zwiększyć przyszłą produktywność programistów i ułatwić utrzymanie kodu. Niestety, refaktoryzacja kodu zazwyczaj dotyczy tylko wewnętrznego kodu źródłowego, ponieważ to właśnie ten kod zespoły mogą łatwo kontrolować i zmieniać.
Kiedy twój zespół tworzy własny program, czasami aktualizuje zewnętrzne komponenty. Z czasem może to stać się odruchem: jeśli komponent dobrze służył organizacji przez wiele miesięcy, zespół domyślnie wierzy, że najnowsza wersja może być bezpiecznie używana, i kontynuuje budowanie wokół tego komponentu, nawet jeśli oznacza to konieczność implementacji lub utrzymywania obejść. Niestety, z czasem może to przyczynić się do zwiększenia długu technicznego. Refaktoryzacja daje zespołom możliwość ponownego przemyślenia, czy nadal chcą polegać na zewnętrznym komponencie. Ważne jest, aby być na bieżąco z rozwojem komponentu i jego mapą drogową, w tym monitorować go pod kątem potencjalnych problemów i podatności, aby upewnić się, że nadal będzie on dobrze dopasowany do potrzeb. Podczas refaktoryzacji uważne rozważenie zewnętrznych komponentów może przyczynić się do zmniejszenia długu technicznego i zminimalizowania rozrostu oprogramowania, który może obniżyć jakość oprogramowania i produktywność programistów.
Sprawdź, na jakim oprogramowaniu bazuje twoja organizacja
Może to zabrzmieć prosto, ale wiedza o tym, jakie oprogramowanie jest używane w organizacji, zwłaszcza oprogramowanie krytyczne pod względem operacyjnym, jest ważna nie tylko ze względu na wymagania audytów IT. Odkrycie podatności w Log4Shell doprowadziło do wyłączenia usług Kanadyjskiej Agencji Skarbowej; w ramach działań prewencyjnych tylko w samej prowincji Quebec wyłączono ponad 4 tysiące rządowych stron internetowych. Agencje i organizacje zostały zmuszone do zawieszenia dostępu do systemów na czas inwentaryzacji swojego oprogramowania, aby ocenić, czy luka rzeczywiście dotyczyła ich działalności. Log4j jest tak rozpowszechniony, że organizacje, w których działają aplikacje Java, mogły prawdopodobnie założyć, że Log4j jest gdzieś wykorzystywany i może wymagać załatania. Jeśli chodzi o oprogramowanie komercyjne, takimi kwestiami powinni zajmować się dostawcy oprogramowania. Ważne jest jednak, aby przy wyborze dostawców upewnić się, że będą oni reagować na problemy występujące w ich produktach, niezależnie od tego, czy są one związane z ich własnym kodem źródłowym, czy z komponentami oprogramowania, których ponownie używają. Poproś dostawców o wykazanie, że dobrze zarządzają decyzjami dotyczącymi ponownego wykorzystania, w tym odpowiednio weryfikują oprogramowanie pod względem jakości i spełniają wymagania licencyjne dotyczące ponownego wykorzystania oprogramowania z wolnym dostępem do kodu źródłowego. Twoja organizacja musi ufać nie tylko dostawcy oprogramowania, ale także wielu innym zespołom programistów, których kod jest wykorzystywany w odległych miejscach.
Kadra kierownicza wyższego szczebla coraz częściej zdaje sobie sprawę, że odporność na zagrożenia cyfrowe jest kwestią o zasadniczym znaczeniu dla ich organizacji. Obowiązkiem liderów jest zrozumienie ryzyka związanego zarówno z nowoczesnymi praktykami tworzenia oprogramowania, jak i z decyzjami o zakupie oprogramowania w pakietach, a także upewnienie się, że ich dział technologiczny dysponuje odpowiednimi procesami umożliwiającymi zarządzanie tym ryzykiem. Chociaż ponowne wykorzystanie oprogramowania ma kluczowe znaczenie dla przyspieszonego tempa innowacji cyfrowych, może ono potencjalnie powodować rozległe, nieprzewidziane i szkodliwe konsekwencje. Zapewnienie ostrożnego zarządzania tą praktyką i rozważenie zarówno krótko-, jak i długoterminowych skutków może zmniejszyć ryzyko, które jest nierozerwalnie związane z korzyściami.
PRZYPISY
1. CVE‑2021‑44228, Mitre, [dostęp: grudzień 2021], https://cve.mitre.org.
2. M. Sojer i J. Henkel, Code Reuse in Open Source Software Development: Quantitative Evidence, Drivers, and Impediments, „Journal of the Association for Information Systems” 11, nr. 12 (marzec 2010): 868‑901.
3. T. Mikkonen i A. Taivalsaari, Software Reuse in the Era of Opportunistic Design, „IEEE Software 36, no. 3 (maj – czerwiec 2019): 105‑111.
4. D. Goodin, Malicious NPM Packages Are Part of a Malware ‘Barrage’ Hitting Repositories, Ars Technica, grudzień 2021, https://arstechnica.com; A. Sharma, Dev Corrupts NPM Libs ‘Colors’ and ‘Faker’ Breaking Thousands of Apps, Bleeping Computer, styczeń 2022, www.bleepingcomputer.com; oraz A. Miller, State of Open Source Security Report 2020 , PDF file (Boston: Snyk, 2020), https://go.snyk.io.
5. T. Seals, ‘Ripple20’ Bugs Impact Hundreds of Millions of Connected Devices, Threatpost, czerwiec 2020, https://threatpost.com.
6. C. Soto‑Valero, N. Harrand, M. Monperrus, et al., A Comprehensive Study of Bloated Dependencies in the Maven Ecosystem, „Empirical Software Engineering” (marzec 2021): 1‑44.
7. H. Solomon, Canadian Websites Temporarily Shut Down as World Scrambles to Mitigate or Patch Log4Shell Vulnerability, „IT World Canada”, Dec. 13, 2021, www.itworldcanada.com.