
Тема безопасной разработки программного обеспечения интересует всё большее количество разработчиков и руководителей. Дополнительным стимулом стал вышедший в конце 2024 года обновлённый ГОСТ Р 56939, в котором описано 25 процессов (мер) для построения безопасной разработки. Это хороший список, но что он означает на практике, например, для Java-разработчиков? Поговорим о сути некоторых процессов и инструментарии.
Статья является переработкой совместного вебинара компаний ООО "ПВС" и Axiom JDK (АО Аксиом). Текстовый вариант содержит дополнительные ссылки, а некоторые моменты рассмотрены более подробно. Полную запись вебинара доступна здесь: "Безопасность приложений: инструменты и практики для Java-разработчиков".
Статья построена так же, как и вебинар: первую часть подготовил Андрей Карпов, затем слово передаётся Алексею Захарову (@AlexZ0).
Безопасная разработка программного обеспечения (РБПО)
Вопросы РБПО естественным образом интересуют тех, кто проходит или планирует проходить сертификацию ФСТЭК. Однако, к теме РБПО наблюдается интерес и у компаний, которые заинтересованы повысить зрелость процессов разработки, вне контекста сертификации.
Например, Виталий Вареница, специалист ЗАО "НПО "Эшелон" по сертификации и тестированию, в своём докладе на вебинаре "Планирование процессов разработки безопасного программного обеспечения" рассказал, что более половины клиентов обращаются к ним с запросом на внедрение РБПО не для сертификации, а для повышения зрелости процессов разработки.
Существуют как зарубежные, так и отечественные наработки в сфере описания процессов безопасной разработки. Примером является "AppSec Table Top: методология безопасной разработки от Positive Technologies", опубликованный 25 сентября 2024 года. Да и вообще история развития методологий безопасной разработки уже весьма длинная: "Secure Software Development Methodologies: A Multivocal Literature Review".
Однако, на мой взгляд, наибольший интерес сейчас представляет ГОСТ Р 56939-2024 — "Защита информации. РАЗРАБОТКА БЕЗОПАСНОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ. Общие требования". Стандарт введён 20 декабря 2024 на замену ГОСТ Р 56939-2016.
Во-первых, это один из самых свежих и актуальных наборов мер, направленных на выпуск безопасного ПО. Во-вторых, он имеет силу в юридической плоскости.
Даже если не стоит задача прохождения сертификации, есть смысл обращаться к этому стандарту для заимствования идей по улучшению отдельных процессов в компании. Понятно, что внедрение РБПО по ГОСТ Р 56939-2024 ресурсозатратное изменение. Есть оценки, что стоимость разработки увеличивается на 10-15 процентов. Поэтому, если не рассматривается задача сертификации, то есть смысл внедрить в первую очередь те процессы, которые с наименьшими затратами принесут наибольшую ползу конкретному проекту.
ГОСТ Р 56939-2024

Стандарт описывает 25 процессов, которые нет возможности рассмотреть в рамках этой одной статьи или вебинара. Собственно, поэтому вместе с УЦ МАСКОМ мы затеяли цикл: "Вокруг РБПО за 25 вебинаров: ГОСТ Р 56939-2024".
Но сейчас задача объять стандарт и не ставится. Хочется просто обратить на него внимание и сказать, что он сможет стать для вас отправной точкой внедрения процессов безопасной разработке в вашей компании.
Его можно рассматривать как своего рода чек-лист мер, которые вы можете изучить, адаптировать под себя и внедрить.
Как я уже сказал, разбор ГОСТ Р 56939-2024 выходит за рамки статьи/вебинара. Но для примера давайте рассмотрим пару описанных в нём процессов, чтобы в целом понять, как он ложится на практическую плоскость.
Думаю, вы не удивитесь, что я выберу наиболее близкие мне меры:
5.8. Формирование и поддержание в актуальном состоянии правил кодирования.
5.10. Статический анализ исходного кода.
Формирование и поддержание в актуальном состоянии правил кодирования
Основное время при работе с кодом программисты тратят не на его написание, а на чтение! Это подтверждено исследованиями, да и вы сами, если программируете и присмотритесь к своей работе, это заметите.
Быстро и много код пишется только в небольших и недавно начатых проектах или в новых модулях — по сути, это тоже новые мини-проекты. Но с ростом проекта всё больше времени тратится на изучение кода, прежде чем будет добавлена новая функциональность или исправлен баг. Бывает даже, что после внесения изменений кода становится не больше, а меньше :)
Есть сразу несколько причин, почему так происходит:
В большом (legacy) проекте всё чаще нужно изменить старое поведение, а не создать что-то принципиальное новое. Все основные функции в каком-то виде уже существует и речь скорее идёт о их развитии или изменении поведения. Соответственно, прежде чем что-то изменить, нужно найти соответствующий код и понять, как он работает.
Часто приходится сопровождать чужой код из-за чего бывает трудно найти нужное место и понять, как всё устроено.
В большом проекте, если вы долго с ним работаете, даже ваш собственный код, со временем становится "чужим". Во-первых, через несколько лет вы его забываете и не помните деталей реализации, а во-вторых, ваши коллеги за это время тоже могли вносить в него правки или рефакторить.
В legacy-проектах можно, по аналогии с годичными кольцами деревьев, наблюдать изменение в стиле написания кода. Чаще всего это связано с появлением новых версий языка и библиотек. Эта разнородность тоже добавляет сложность в понимание старых частей проекта.
Известно, что с ростом проекта плотность ошибок растёт нелинейно. То есть чем больше кода, тем выше вероятность того, что при написании или изменении кода будет внесена ошибка. Это объясняется ростом взаимосвязей разных частей проекта, которые сложно учитывать. Рост сложности понимания влияет и на рост процента времени, который приходится тратить человеку, прежде чем сделать правку.
Думаю, вы и сами сможете добавить пару пунктов к этому списку.
Из сказанного вытекает, что код требуется делать по возможности простым для восприятия (чтения). Также очень важно, чтобы весь код был единообразно оформлен. Если оформление единообразно, то проще прочитать, понять и исправить код коллег.
Это можно достичь, если сформировать, принять и поддерживать в актуальном состоянии правила кодирования, что, собственно, и описано в пункте ГОСТ-а, который мы рассматриваем. То есть следует разработать регламент оформления кода и систематически его придерживаться.
Молодые специалисты могут возражать против принятых правил, обосновывая это тем, что они ограничивают их творчество и скорость написание кода, либо тем, что правила устарели и не учитывают какие-то моменты.
Они не правы. Я считаю, что даже не очень хороший стандарт лучше, чем его отсутствие. Однако, я не говорю, что надо мучится и преодолевать неудобства. Можно и нужно совершенствовать регламенты. Собственно, это отражено даже в названии рекомендуемого восьмого процесса РБПО — "формирование и поддержание в актуальном состоянии правил кодирования".
В любом случае код должен оформляться единообразно. Иначе неизбежны проблемы при совместной разработке и поддержке проекта. А мы как раз говорим о проектах, где участвует много разработчиков, а не об индивидуальном пет-проекте.
Есть ещё одна проблема, которая возникает если нет единого подхода к написанию и оформлению кода — как вносить правки в код коллег, оформленный в их собственном стиле? Хорошего варианта нет:
Написать нужный код в своём стиле. Постепенно получится каша из несвязанных стилей. Это то же самое, когда вообще ни у кого нет никакого стиля написания кода. Код со временем при совместной работе будет становиться всё хуже и непонятней всем сразу.
Постараться подстроиться под код коллег и написать в их стиле. На практике не сработает, так как на самом деле программист не знает, что это за стиль. А если даже ему расскажут, он всё равно забудет или запутается, пытаясь помнить все варианты написания. В общем, и это не рабочий подход.
Отрефакторить код коллег под свой стиль. Большая пустая трата времени и большие diff-ы, в которых будет невозможно понять, где рефакторинг, а где собственно нужные изменения.
Надеюсь, что у вас в компании уже давно принят стандарт кодирования и всё написанное выше можно было не читать, так как это очевидно. Однако если стандарта кодирования нет, это хороший момент об этом задуматься. Это важно даже вне разреза темы РБПО.
Если я всё ещё не убедил, расскажу последнюю историю. Общаясь с одним человеком, который проработал в коммерческой компании почти от её основания до успешного большого бизнеса, я спросил, что он бы устроил по-другому в работе, если вернулся лет на 15 назад? Ответ, в том числе, содержал следующий момент:
> Я бы настоял на принятии единого стандарта кодирования на всю компанию. Мы упустили этот момент, и сейчас мы по факту имеем отличающиеся стандарты кодирования в разных командах, работающих над своими проектами. Это очень неудобно, но сейчас внедрять единый стиль и переформатировать код всех этих проектов нереально.
В общем, чем раньше вы позаботитесь о единообразии, тем лучше!
Итак, вы собрались составить правила кодирования или, пользуясь случаем, хотите их обновить. С чего можно начать?
Думаю, лучше всего начать с такой замечательной книги, как "Совершенный код" Стива Макконнелла ("Code Complete", Steve McConnell).

Из неё можно почерпнуть очень много, например, про табличное форматирование кода. Оно помогает сделать код визуально более красивым и лёгким для восприятия. А ещё, этот один из способов бороться с "кодом-колбасой" — так я называю длинные строчки кода.
Кстати, Java-программы весьма страдают от длинных строк кода. Даже есть всякие мемы на эту тему, типа такого:

Для Java-разработчиков проблема длинных строк весьма актуальна (впрочем не только для них :). Длинные строки сложно читать и проверять. Особенно если они настолько длинные, что не помещаются на экран и приходится использовать прокрутку для их просмотра.
Пример рефакторинга длинной строки можно посмотреть в статье "Учимся рефакторить код на примере багов в TDengine, часть 1: про колбасу", откуда как раз взята картинка.
Ограничение на длину строк — это один из примеров того, что можно включить в стандарт кодирования.
Заметить опечатку мешают не только длинные, но неаккуратно отформатированные строки кода. Ниже пример функции из проекта Apache Flink.
@Override
public boolean equals(Object o)
{
....
CheckpointStatistics that = (CheckpointStatistics) o;
return id == that.id &&
savepoint == that.savepoint &&
triggerTimestamp == that.triggerTimestamp &&
latestAckTimestamp == that.latestAckTimestamp &&
stateSize == that.stateSize &&
duration == that.duration &&
alignmentBuffered == that.alignmentBuffered &&
processedData == processedData &&
persistedData == that.persistedData &&
numSubtasks == that.numSubtasks &&
numAckSubtasks == that.numAckSubtasks &&
status == that.status &&
Objects.equals(checkpointType, that.checkpointType) &&
Objects.equals(
checkpointStatisticsPerTask,
that.checkpointStatisticsPerTask);
}
Видите ошибку? Поскольку вы знаете, что она здесь есть, думаю, вы её найдёте. А вот не зная, сомнительно, что вы сможете сохранить внимание при изучении этого кода в процессе обзора и найти её. Собственно, разработчики её и не нашли, раз мы её здесь изучаем.
Ошибка найдена с помощью статического анализатора кода PVS-Studio: V6001 There are identical sub-expressions 'processedData' to the left and to the right of the '==' operator. CheckpointStatistics.java(229)
Вот она:
processedData == processedData
Переменная сравнивается сама с собой. Хотя ошибка найдена, лучше заниматься не поиском, а профилактикой её появления. Если оформив код более красиво (таблицей), ошибка более заметна:
return id == that.id &&
savepoint == that.savepoint &&
triggerTimestamp == that.triggerTimestamp &&
latestAckTimestamp == that.latestAckTimestamp &&
stateSize == that.stateSize &&
duration == that.duration &&
alignmentBuffered == that.alignmentBuffered &&
processedData == processedData &&
persistedData == that.persistedData &&
numSubtasks == that.numSubtasks &&
numAckSubtasks == that.numAckSubtasks &&
status == that.status &&
Objects.equals( checkpointType,
that.checkpointType) &&
Objects.equals( checkpointStatisticsPerTask,
that.checkpointStatisticsPerTask);
Конечно, это не гарантирует, что ошибка не будет пропущена. Речь о том, что снизилась вероятность её допустить и просмотреть на обзорах кода.
Чтобы расставлять меньше пробелов и реже переформатировать код, лучше ещё доработать стиль оформления:
return id == that.id
&& savepoint == that.savepoint
&& triggerTimestamp == that.triggerTimestamp
&& latestAckTimestamp == that.latestAckTimestamp
&& stateSize == that.stateSize
&& duration == that.duration
&& alignmentBuffered == that.alignmentBuffered
&& processedData == processedData
&& persistedData == that.persistedData
&& numSubtasks == that.numSubtasks
&& numAckSubtasks == that.numAckSubtasks
&& status == that.status
&& Objects.equals( checkpointType,
that.checkpointType)
&& Objects.equals( checkpointStatisticsPerTask,
that.checkpointStatisticsPerTask);
Подробное объяснение, чем такой вариант лучше, выходит за рамки данной публикации. Предлагаю вашему вниманию эту ссылку "Форматирование кода таблицей", где это момент объясняется на примерах.
Форматирование кода таблицей не обязательно должно быть включено в ваш набор правил кодирования — это просто пример, что можно почерпнуть из книги и внедрить. Можно найти и другие источники для вдохновения.
Внедрение стандарта кодирования повысит общий уровень вашей разработки, что положительно повлияет на безопасность разрабатываемых приложений. Так что меры, перечисляемые ГОСТ Р 56939-2024 имеют ценность в совершенно практической плоскости.
Дополнительно можно настроить и использовать инструменты автоматизированного форматирования кода, такие как:
Статический анализ исходного кода
Опасная для меня глава, так как я могу увлечься и накатать страниц 50 по этой теме :) Поэтому сейчас я сознательно буду себя сдерживать. Постараюсь написать минимально необходимое с уклоном в безопасность.
У статического анализа есть несколько направлений применения:
Поиск ошибок и опечаток. Статический анализ кода в классическом и распространённом понимании.
Поиск потенциальных уязвимостей (критических ошибок по терминологии ГОСТ Р 71207-2024). Ещё это называют Static Application Security Testing – SAST.
Поддержка определённых общепринятых стандартов. Сюда входит не только поиск ошибок, но и ограничение программистов в используемых конструкций языка. Известный представитель из мира C: MISRA C.
Поддержка стандартов, принятых в конкретной компании, проверка оформления кода в рамках локальных стандартов оформления кода.
Стилистический анализ. Выдача рекомендаций по именованию переменных и классов. Ограничение цикломатической сложности и т.п.
Есть и другие направления или ответвления. Например, анализ кода с целью построения диаграмм взаимосвязей различных классов.
Конкретный статический анализатор может быть нацелен как на один из этих пунктов, так и сочетать несколько из них.
Однако обсуждая РБПО, я остановлюсь только на втором направлении — поиске потенциальных уязвимостей. Тем более про это существует ГОСТ Р 71207-2024 — "Статический анализ программного обеспечения", который применяется совместно с ГОСТ Р 56939.
ГОСТ Р 71207-2024 формализует, что, говоря о безопасной разработке, надо искать не придираться к именованию переменных, а искать критические ошибки.
> Критическая ошибка в программе: Ошибка, которая может привести к нарушению безопасности обрабатываемой информации. [ГОСТ Р 71207-2024, п. 3.1.13]
Для языка Java этот стандарт перечисляет следующие типы критических ошибок (п. 6.3):
Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.);
Ошибки целочисленного переполнения и некорректного совместного использования знаковых и беззнаковых чисел;
Ошибки переполнения буфера (записи или чтения за пределами выделенной для буфера памяти);
Ошибки некорректного использования системных процедур и интерфейсов, связанных с обеспечением информационной безопасности (шифрования, разграничения доступа и пр.);
Ошибки при работе с многопоточными примитивами (интерфейсами запуска потоков на выполнение, синхронизации и обмена данными между потоками и пр.).
Дополнительно в рамках "Испытания статических анализаторов исходных кодов компилируемых и динамических языков программирования под руководством ФСТЭК России" этот список был расширен следующим категориями:
Ошибки разыменования нулевой ссылки;
Ошибки деления на ноль;
Ошибки управления динамической памятью;
Ошибки утечек памяти и ресурсов.
Статические анализаторы, совместимые с ГОСТ Р 71207-2024, должны уметь обнаруживать все эти виды ошибок, а также соответствовать ряду других требований. Подробное рассмотрение этого стандарта избыточно в этой статье, тем более я уже записал цикл ознакомительных докладов:
ГОСТ Р 71207-2024 — Общее описание и актуальность;
ГОСТ Р 71207-2024 — Терминология;
ГОСТ Р 71207-2024 — Критические ошибки;
ГОСТ Р 71207-2024 — Технологии анализа кода;
ГОСТ Р 71207-2024 — Процессы.
Использование статических анализаторов, поддерживающих ГОСТ Р 71207-2024, позволяет выявить множество дефектов ещё на этапе написания кода, что повышает качество и надёжность программного продукта.
Одним из таких анализаторов является PVS-Studio. Поддерживает анализ программ на языке C, C++, C#, Java. Возможности использования для сертификаций:
Включён в Реестр российского ПО: запись N 9837 от 18.03.2021.
Удовлетворяет требованиям, описанным в "Методике выявления уязвимостей и недекларированных возможностей в программном обеспечении" от 25 декабря 2020 г.
Разрабатывается с учётом требований, предъявляемых к статическим анализаторам в ГОСТ Р 71207-2024 (подробнее).
Применяется испытательными лабораториями в рамках работ по сертификационным испытаниям программных продуктов.
Имеет плагин для открытой среды разработки OpenIDE, защищённой от санкций и соответствующей законодательству РФ.
Теперь посмотрим на практике, что подразумевает стандарт, говоря о выявлении ошибок. Приведу пару фрагментов кода из реальных проектов, в которых были найдены ошибки с помощью PVS-Studio. Первый фрагмент взят из проекта WildFly:
private volatile ExpressionFactory factory;
....
@Override
public ExpressionFactory getExpressionFactory() {
if (factory == null) {
synchronized (this) {
if (factory == null) {
factory = delegate.getExpressionFactory();
for (ExpressionFactoryWrapper wrapper : wrapperList) {
factory = wrapper.wrap(factory, servletContext);
}
}
}
}
return factory;
}
Предупреждение PVS-Studio: V6082 Unsafe double-checked locking. A previously assigned object may be replaced by another object. JspApplicationContextWrapper.java(74), JspApplicationContextWrapper.java(72)
В коде неправильно реализован паттерн "блокировка с двойной проверкой" (double-checked locking). Согласно ГОСТ Р 71207-2024 этот баг относится к категории "Ошибки при работе с многопоточными примитивами".
После выполнения:
factory = delegate.getExpressionFactory();
Второй поток может прийти в функцию getExpressionFactory
и она вернёт недосозданный объект.
Комментарий Алексея Захарова.
Мы в компании Axiom JDK, разрабатываем Libercat — поддерживаемый российский безопасный сервер приложений, реализующий спецификации Java EE/Jakarta EE. Является заменой как раз таких решений, как WildFly.
Собственно, вот какой интересный момент. Используя процессы безопасной разработки ПО в своей компании, мы защищены по крайней мере от подобных ошибок, так как активно используем статические анализаторы и другие меры. Т.е. по крайней мере эту ошибку мы бы нашли и справили ещё на этапе написания кода.
Второй фрагмент кода взят из проекта Apache Hive:
public void logSargResult(int stripeIx, boolean[] rgsToRead)
{
....
long val = 0;
for (int j = 0; j < 64; ++j) {
int ix = valOffset + j;
if (rgsToRead.length == ix) break;
if (!rgsToRead[ix]) continue;
val = val | (1 << j);
}
....
}
Предупреждение PVS-Studio: V6034 Shift by the value of 'j' could be inconsistent with the size of type: 'j' = [0 .. 63]. IoTrace.java 272
ГОСТ классифицирует это как критическую ошибку целочисленного переполнения. Числовой литерал 1
имеет тип int
и при попытке произвести сдвиг влево более чем на 31 разряд произойдёт переполнение. Правильный вариант: (1L << j)
.
Вот какие реальные ошибки могут и должны выявлять статические анализаторы кода.
Другие процессы
Мы посмотрели на маленький кусочек темы РБПО и ГОСТ Р 56939-2024. Вопросы построения РБПО распространяются гораздо дальше написания и проверок кода. В них входит и обучение сотрудников, и безопасная инфраструктура и так далее. Надеюсь, мне удалось вас заинтересовать.
Далее я передаю слово Алексею Захарову из компании Axiom JDK, стоящей на страже безопасности Java.
Во-первых, они построили в своей компании процессы безопасной разработки и их продукты сертифицированы. Во-вторых, они предоставляют своим пользователям возможность усовершенствовать свои процессы с точки зрения РБПО и ГОСТ Р 56939-2024 по следующим направлениям:
5.12. Использование безопасной системы сборки программного обеспечения.
5.13. Обеспечение безопасности сборочной среды программного обеспечения.
5.21. Безопасная поставка программного обеспечения пользователям.
Но думаю про всё это лучше напишет Алексей.
Axiom JDK, Алексей Захаров
Кратко расскажу, как Axiom JDK поддерживает безопасную разработку:
Мы активно используем и развиваем процессную дисциплину (сертификации ФСТЭК, соответствие ГОСТ Р 56939-2024);
Наши разработчики внедряют технические инновации, такие как безопасные архитектуры, процессы устранения уязвимостей CVE;
Технологическое подразделение развивает экосистемную безопасность (поддержка российских ОС/оборудования, участие в стандартизации, развитие российских безопасных средств разработки и интеграция с системами проверки кода).
Начну с того, что мы в первую очередь рекомендуем начинать с пункта ГОСТ 5.9 Экспертиза исходного кода, поскольку знание кодовой базы продуктов — это необходимость!
Наши продукты реализуют спецификацию, в которой >1500 страниц, например, JVM 23.
Объем верифицированного исходного кода российского дистрибутива среды исполнения (JRE) составляет 16 млн. строк. У нас 6 LTS релизов, а это 94 млн. строк.
Разумеется, такие объёмы кода нужно проверять автоматизированными средствами при выпуске каждого релиза и обновления.
Конечно, это можно делать вручную, но мы придерживаемся промышленного подхода и создали для наших продуктов конвейер обработки артефактов, начиная от исходных кодов и заканчивая композиционным анализом, регрессионными тестами и фаззингом.
AXIOM РБПО и доверенный репозиторий

Также немаловажным аспектом нашей разработки является создание приложений, соответствующих требованиям ФСТЭК, которые от нас требуют расширения спецификации и функций продукта.
Требования ФСТЭК и что мы обнаружили
Применение фаззинга и санитайзеров позволяет выявить скрытые дефекты, возможности обхода безопасности и повышения привилегий. Например, при использовании средств проверки кода мы применили "Undefined Behavior Sanitizer", который обнаружил в С1 JIT знаковое переполнение значения int
, и на некоторых аппаратных платформах оно приводит к возникновению исключений на уровне оборудования. Если его не обработать, то это приводит к ошибкам. Вот пример одной из них:

В качестве решения мы добавили обработку исключения для поддержки платформ, которая позволила восстановить корректность работы компилятора С1.
Далее перейдём к процессу 5.12. — Использование безопасной системы сборки программного обеспечения.
Мы используем свой проверенный компилятор для сборки JDK.
Мы создали свои доверенные Gradle и Maven, которые собрали своим компилятором Java. Эти сборки позволяют гарантировать чистоту сборочного конвейера. Дополнительно они вносят в JAR-файлы библиотек подписи с информацией, что сборка библиотеки произведена компанией Axiom JDK.
Перейдём к следующему процессу 5.13. — Обеспечение безопасности сборочной среды программного обеспечения.
Для этой задачи мы используем изолированную виртуальную инфраструктуру, в которой более 20 физических серверов и более 100 виртуальных машин. На этой инфраструктуре мы проводим сборку и тестирование наших продуктов для разных аппаратных платформ и операционных систем.
Ещё один немаловажный процесс 5.21. — Безопасная поставка программного обеспечения пользователям.
Он позволяет передавать только те версии, которые подписанны цифровой подписью (GUID) и файлом контрольной суммы.

Теперь перейдём к процессу работы с прикладным ПО. В нашем примере мы будем использовать плагин PVS-Studio и готовую платформу создания приложений JMIX.
Установка плагина PVS-Studio в Open IDE
1. Установить плагин можно из маркетплейса:

2. Если нет доступа в Интернет, то есть альтернатива (для закрытых сред) — установить плагин из файла:

3. Далее создаём проект. Мы будем использовать проект на примере приложений JMIX, который быстро — буквально за минуты — позволяет создать рабочий прототип:

Обращаем внимание, что по умолчанию используется JDK от компании Axiom JDK.

4. После создания и запуска приложения необходимо провести проверку кода при помощи плагина PVS-Studio. Для этого просто воспользуемся контекстным меню IDE:

5. Проверка кода проводится при помощи PVS-Studio. В итоге мы получаем обнаруженную рекомендацию обработать и использовать возвращённое функцией значение:

6. При необходимости можно получить пояснения на сайте PVS-Studio:

Мы только что рассмотрели только один базовый слой проверки приложения. Но в составе приложения, как правило, содержатся дополнительные компоненты: сервера веб приложений, контейнеры, — и для обеспечения их проверок необходимо затратить большое количество времени.
Мы предлагаем другой подход использования готовых компонент экосистемы Axiom JDK.
Приведу пример замены в проекте Spring Boot сервера приложений Tomcat на сервер Libercat Certified.
Кратко опишу процесс только для Gradle.
Конфигурация для Gradle
1. Создаём образ репозитория Nexus.
Для этого выполняем следующую команду:
docker pull sonatype/nexus3:latest
docker run -d -p 8081:8081 --name nexus sonatype/nexus3:latest
2. Настраиваем проект на локальный репозиторий.
Добавляем файл gradle.properties
:
nexusUrl = http://localhost:8081
В файле build.gradle
добавляем строки:
repositories {
maven {
url "$nexusUrl/repository/maven-central/"
allowInsecureProtocol true
}
}
В файле settings.gradle
добавляем строки:
pluginManagement {
repositories {
maven {
url "http://localhost:8081/repository/gradle-plugins/"
allowInsecureProtocol true
}
}
}
rootProject.name = 'spring-boot'
Для проверки необходимо запустить сборку проекта, и в момент обращения к репозиториям будет произведено кеширование необходимых библиотек. Как подтверждение работоспособности прокси Maven Central, в репозитории появятся библиотеки.
После сборки проекта и загрузки библиотек можно увидеть текущие версии Tomcat или Libercat, которые используются приложением. Для этого можно воспользоваться поиском:

Необходимо загрузить предоставленные jar-файлы в ваш Maven репозиторий. Список используемых библиотек зависит от вашего приложения, но как минимум мы рекомендуем загрузить следующие файлы:
tomcat-embed-core.jar tomcat-embed-websocket.jar tomcat-embed-el.jar
Эти файлы можно получить, разместив запрос в личном кабинете на сайте AxiomJDK. Запрос будет обработан для действующих клиентов компании с лицензией на Libercat. Лицензия для разработчиков доступна в рамках подписки корпоративного разработчика.
Важно! При загрузке поле Classifier
оставляем пустым.
Пример файла build.gradle для Gradle:

1. Комментируем обращение к внешнему репозиторию и оставляем только внутренний:

2. Модифицируем файл сборки приложения.
Для Gradle
В сборочном файле (build.gradle
) вашего приложения необходимо явно переопределить версию сервера приложений:
ext['tomcat.version'] = '10.1.26-2-certified'
Теперь при сборке приложения Spring Boot автоматически будет использовать Libercat Certified Embedded.
Успешный запуск выглядит следующим образом:

Процесс демонстрирует повышение уровня безопасности приложения переводом c приложения на Spring c сервера Tomcat на Libercat Certified.
Таким образом, мы использовали крупноблочную сборку и задействовали сертифицированную защищённую версию сервера приложений. Это намного быстрее, чем проводить самостоятельную проверку кода, исправления, сертификацию и устранение уязвимостей.
Авторы
Андрей Карпов. Один из основателей проекта PVS-Studio (ООО "ПВС"). Автор статей на тему статического анализа кода и написания качественного кода. Сейчас активно занимается тематикой разработки безопасного программного обеспечения и ведёт цикл публикаций, посвящённый ГОСТ Р 56939-2024, в своём Telegram-канале "Бестиарий программирования".
Алексей Захаров ( @AlexZ0). Директор по технологическому консалтингу Axiom JDK (Telegram-канал — Axiom JDK). Развивает подходы к внедрению безопасных продуктов. Выступает на конференциях и мероприятиях по ИБ и ИТ-технологиям. Работал директором по стратегии и бизнес-контролю в компании "МойОфис", где занимался в том числе и разработкой концепции доверенных решений на ПАК с применением сертифицированных ФСТЭК версий продуктов компании. В компании "СКАЛА-Р" принимал участие в сознании и продвижении уникальных доверенных ПАК для объектов КИИ. Участвовал в проектах развития продуктов роботизации для корпоративных заказчиков с целью повышения их уровня безопасности и соответствия требованиям индустрии и правилам ИБ в компании PIX Robotics в лице руководителя группы технологических решений. 20 лет опыта работы в компаниях Microsoft и Oracle.