﻿# Аннотирование Java кода в формате JSON

Способы подключения файла c аннотациями

Подробнее о способе подключения файла аннотаций вы можете узнать в [этой](https://pvs-studio.ru/ru/docs/manual/6810/#how_to_enable) документации\.

## Структура файла с аннотациями

Содержимое файла — JSON\-объект, состоящий из трёх обязательных полей: `language`, `version` и `annotations`\. 

Поле `language` должно иметь значение `java`\. Поле `version` принимает значение целого типа и задаёт версию механизма\. В зависимости от значения файл с разметкой может обрабатываться по\-разному\. На данный момент поддерживается только одно значение — 1\.

Поле `annotations` — массив объектов "аннотация":

```cpp
{
  "language": "java",
  "version": 1,
  "annotations":
  [
    {
      ...
    },
    {
      ...
    }
  ]
}
```

На данный момент существуют аннотации методов и конструкторов\.

## Аннотации для taint\-анализа 

В анализаторе существует ряд аннотаций для [taint\-анализа](https://pvs-studio.ru/ru/blog/terms/6496/)\. С их помощью можно размечать источники и приёмники заражения\. Также существует возможность помечать методы/конструкторы, которые производят валидацию taint\-данных\. Таким образом, если taint\-данные прошли валидацию, то при их попадании в приёмник предупреждения анализатора не будет\.

За каждый из видов уязвимостей отвечает отдельное диагностическое правило\. На данный момент в анализаторе представлены следующие taint\-диагностики:

* [V5309](https://pvs-studio.ru/ru/docs/warnings/v5309/) — SQL injection;
* [V5310](https://pvs-studio.ru/ru/docs/warnings/v5310/) — OS command injection;
* [V5311](https://pvs-studio.ru/ru/docs/warnings/v5311/) — OS argument injection;
* [V5312](https://pvs-studio.ru/ru/docs/warnings/v5312/) — XPath injection;
* [V5319](https://pvs-studio.ru/ru/docs/warnings/v5319/) — Log injection;
* [V5320](https://pvs-studio.ru/ru/docs/warnings/v5320/) — Configuration injection;
* [V5321](https://pvs-studio.ru/ru/docs/warnings/v5321/) — LDAP injection;
* [V5322](https://pvs-studio.ru/ru/docs/warnings/v5322/) — Reflection injection;
* [V5323](https://pvs-studio.ru/ru/docs/warnings/v5323/) — Potentially tainted data is used to define CORS policy;
* [V5327](https://pvs-studio.ru/ru/docs/warnings/v5327/) — Regex injection;
* [V5330](https://pvs-studio.ru/ru/docs/warnings/v5330/) — XSS injection;
* [V5332](https://pvs-studio.ru/ru/docs/warnings/v5332/) — Path traversal vulnerability\.

### Принцип работы taint\-аннотаций

Для каждого из диагностических правил существуют специальные аннотации, которые позволяют разметить приёмники и методы/конструкторы, производящие валидацию\.

Что касается источников taint\-данных, то они являются общими для всех диагностик\. Такие данные также можно разметить с помощью аннотаций\.

**Примечание\.** Атрибуты для разметки taint\-аннотаций описаны в следующих разделах\.  

Стоит отметить, что, помимо пользовательских аннотаций, в анализаторе уже имеется ряд taint\-аннотаций для различных библиотек\. Например, при передаче результата выполнения метода `Console.readLine` в метод `Statement.execute` возможно возникновение SQL injection\. В анализаторе есть аннотации, которые говорят, что `Console.readLine` — источник taint\-данных, а `Statement.execute ` — приёмник, при попадании в который taint\-данных может возникнуть SQL injection\.

Таким образом, размечая источники taint\-данных, анализатор будет учитывать их для уже существующих приёмников и наоборот\. Если добавить аннотацию приёмника, то анализатор будет выдавать предупреждение при попадании в него уже размеченных источников taint\-данных \(например, `Console.readLine`\)\. 

## Аннотации методов

**Примечание\.** Объект аннотации метода должен содержать хотя бы одно опциональное поле\.

Объект аннотации метода состоит из следующих полей:

### Поле "type"

Обязательное поле\. Принимает строку со значением `method`\.

### Поле "package"

Обязательное поле\. Принимает строку с именем пространства имён, которое содержит метод\.

### Поле "type\_name"

Обязательное поле\. Принимает строку с именем класса, в котором определён метод\. 

### Поле "method\_name"

Обязательное поле\. Принимает строку с именем метода\. 

**Примечание**\. Для аннотирования конструктора необходимо использовать `<init>`\.

### Поле "attributes"

Опциональное поле\. Массив строк, который задаёт свойства сущности\.

#### Возможные атрибуты метода 

|\\\#|Название атрибута|Описание атрибута|
|---|---|---|
|1|sql\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к SQL Injection|
|2|os\\\_command\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к OS Command Injection|
|3|xpath\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к XPath Injection|
|4|configuration\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к Configuration Injection|
|5|ldap\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к LDAP Injection|
|6|reflection\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к Reflection Injection|
|7|regex\\\_sink|Передача заражённых данных в параметры этого метода приводит к Regex Injection|
|8|xss\\\_injection\\\_sink|Передача заражённых данных в параметры этого метода приводит к XSS Injection|
|9|path\\\_traversal\\\_sink|Передача заражённых данных в параметры этого метода приводит к Path Traversal Vulnerability|



### Поле "params"

Опциональное поле\.

Аннотирование параметров необходимо для определения нужного для разметки метода\. Отсутствие данного поля означает любое количество параметров любых типов\. Пустой массив параметров \(`[ ]`\) означает отсутствие параметров\.

Объект аннотации параметра состоит из следующих полей:

#### Поле "package"

Обязательное поле\. Принимает строку с именем пакета, которое содержит тип параметра\.

#### Поле "type\_name"

Обязательное поле\. Принимает строку с именем класса, в котором определён тип параметра\. 

### Поле "returns"

Опциональное поле\. Объект возвращаемого значения, состоит из единственного поля:

#### Поле "attributes"

Опциональное поле\. Массив строк, который задаёт свойства возвращаемого значения метода\.

**Возможные атрибуты возвращаемого значения**

|\\\#|Название атрибута|Описание атрибута|
|---|---|---|
|1|common\\\_source|Возвращаемое значение является источником заражённых данных|
|2|web\\\_source|Возвращаемое значение является веб источником заражённых данных|
|3|potential\\\_sql\\\_sanitization|Возвращаемое значение является санитизированным т SQL Injection|
|4|potential\\\_os\\\_command\\\_sanitization|Возвращаемое значение является санитизированным от OS Command Injection|
|5|potential\\\_xpath\\\_sanitization|Возвращаемое значение является санитизированным от XPath Injection|
|6|potential\\\_log\\\_sanitizaton|Возвращаемое значение является санитизированным от Log Injection|
|7|potential\\\_configuration\\\_sanitization|Возвращаемое значение является санитизированным от Configuration Injection|
|8|potential\\\_ldap\\\_sanitization|Возвращаемое значение является санитизированным от LDAP Injection|
|9|potential\\\_reflection\\\_sanitization|Возвращаемое значение является санитизированным от Reflection Injection|
|10|regex\\\_sanitization|Возвращаемое значение является санитизированным от Regex Injection|
|11|xss\\\_input\\\_sanitization|Возвращаемое значение является санитизированным от XSS Injection|
|12|potential\\\_path\\\_traversal\\\_sanitization|Возвращаемое значение является санитизированным от Path Traversal Vulnerability|

## Схема JSON

[Схема JSON](https://files.pvs-studio.com/media/custom_annotations/v1/java-annotations.schema.json) поставляется в дистрибутиве или доступна по ссылке\.

## Примеры

### Аннотация метода

Рассмотрим метод: 

```cpp
package com.example;

public class MyClass {
  public string getUserInput() {
    ....
  }
}
```

Допустим, данный метод возвращает пользовательский ввод, который может содержать taint\-данные\. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом: 

```cpp
{
  "version": 1,
  "language": "java",
  "annotations": [
    {
      "type": "method",
      "package_name": "com.example",
      "type_name": "MyClass",
      "method_name": "getUserInput",
      "returns": {
        "attributes": [ "common_source" ]
      }
    }
  ]
}
```

### Аннотация метода/конструктора, тип параметра которых неважен

Рассмотрим две перегрузки метода `getUserInput`: 

```cpp
package com.example;

public class MyClass {

  public string getUserInput(string str) {
    ....
  }

  public string getUserInput(int index) {
    ....
  }
}
```

Допустим, вне зависимости от типа параметра данный метод возвращает пользовательский ввод, который может содержать taint\-данные\. Аннотация, которая позволит анализатору понять это, будет выглядеть следующим образом: 

```cpp
{
  "version": 1,
  "language": "java",
  "annotations": [
    {
      "type": "method",
      "namespace_name": "com.example",
      "type_name": "MyClass",
      "method_name": "getUserInput",
      "returns": {
        "attributes": [ "common_source " ]
      }
    }
  ]
}
```

В данном случае для первого параметра нет аннотаций\. Также при подборе аннотации метода неважно, какой тип будет иметь первый параметр, поэтому его аннотация представлена пустым объектом\.

### Аннотация метода/конструктора с конкретными параметрами

Рассмотрим методы с различными параметрами:

```cpp
package org.example;

public class Sink {

    public void sink(String input) {
        ....
    }

    public void sink(String input, String sanitization) {
        ....
    }
}
```

Если мы считаем, что стоком является лишь первая версия метода, то её аннотация будет выглядеть следующим образом:

```cpp
{
    "language": "java",
    "version": 1,
    "annotations": [
        {
            "type": "method",
            "package": "org.example",
            "type_name": "Sink",
            "method_name": "sink",
            "params": [
                { 
                    "package": "java.lang",
                    "type_name": "String"
                }
            ],
            "attributes": [
                "sql_injection_sink"
            ]
        }
    ]
```

\}

Таким образом, в следующем фрагменте кода анализатор сформирует предупреждение лишь на один из вызовов метода:

```cpp
package org.example;

public class Main {

    public static void main(String[] args) {
        var sinkObj = new Sink();
        sinkObj.sink(args[0]);                // V5309
        sinkObj.sink(args[0], "sanitized");   // нет срабатывания
    }
}
```