>
>
Annotating C# entities in JSON format


Annotating C# entities in JSON format

Note. Currently, the C# analyzer supports annotations only for taint analysis. User annotations for general purposes will be supported later.

Ways to register the annotation file

You can learn more about how to enable the annotation file in this documentation.

Structure of the annotation file

The file content is a JSON object consisting of three mandatory fields: language, version, and annotations.

The language field must receive the value 'csharp'. The version field takes an integer-type value and specifies the version of the mechanism. Depending on the value, the markup file can be processed differently. Currently, only the value 1 is supported.

The annotations field is an array of "annotation" objects:

{
  "language": "csharp",
  "version": 1,
  "annotations":
  [
    {
      ...
    },
    {
      ...
    }
  ]
}

Annotations can be of three types:

  • method annotations
  • constructor annotations
  • property annotations.

Annotations for taint analysis

The PVS-Studio analyzer provides a range of annotations for taint analysis, which can be used to track taint sources and sinks. It is also possible to mark up methods/constructors that validate tainted data. Therefore, if the tainted data has been validated, the analyzer will not issue a warning when the data reaches the sink.

A different diagnostic rule is used to handle each type of vulnerability. At the moment, the analyzer provides the following diagnostic rules for identifying tainted data:

  • V5608 — SQL injection
  • V5609 — Path traversal vulnerability
  • V5610 — XSS vulnerability
  • V5611 — Insecure deserialization vulnerability
  • V5614 — XXE vulnerability
  • V5615 — XEE vulnerability
  • V5616 — Command injection
  • V5618 — Server-side request forgery
  • V5619 — Log injection
  • V5620 — LDAP injection
  • V5622 — XPath injection
  • V5623 — Open redirect vulnerability
  • V5624 — Configuration vulnerability
  • V5626 — ReDoS vulnerability
  • V5627 — NoSQL injection
  • V5628 — Zip Slip vulnerability.

How taint annotations operate

Each diagnostic rule has special annotations to mark taint sinks and methods/constructors that validate tainted data.

As for taint data sources, they are common to all diagnostic rules. However, such data can also be annotated.

Note: The attributes for taint annotations are detailed in the following documentation sections.

It's important to note that, in addition to user annotations, the analyzer already provides a range of taint annotations for various libraries. To give an example, passing the result of the System.Console.ReadLine method to the System.Data.SqlClient.SqlCommand constructor can potentially lead to SQL injection. The analyzer provides annotations that indicate System.Console.ReadLine as a source of tainted data and System.Data.SqlClient.SqlCommand as a sink where this tainted data could lead to SQL injection.

Thus, if we annotate the source of tainted data, the analyzer will recognize its exposure to existing sinks, and vice versa. If the sink is annotated, the analyzer will issue a warning when it encounters previously marked tainted data sources, such as System.Console.ReadLine.

Method annotations

Note: The method annotation object must contain at least one optional field.

The method annotation object consists of the following fields:

The "type" field

The mandatory field. It takes a string with the method value.

The "namespace_name" field

The mandatory field. It takes a string specifying the name of the namespace that contains the method.

The "type_name" field

The mandatory field. It takes a string specifying the name of the class where the method is defined.

The "method_name" field

The mandatory field. It takes a string with the name of the method.

The "attributes" field

The optional field. The array of strings that specifies the properties of an entity.

Possible method attributes

#

Attribute name

Attribute description

1

not_apply_to_child_class

The annotation is not applied when the annotated method is called on an object of a child class.

2

caller_is_xml_parser

The object calling the method is an XML parser, which could be vulnerable (V5614, V5615).

The "params" field

The optional field. This field is described in the "Parameter annotations" section.

The "returns" field

Note. The return value annotation object must either include both the 'namespace_name' and 'type_name' fields or have both fields absent (or set to null). If both fields are absent, the type of the return value will not be considered when selecting an annotation.

The optional field. The return value object consists of the following fields:

The "namespace_name" field

The optional field. It takes a string specifying the name of the namespace that contains the type of the method return value.

The "type_name" field

The optional field. It takes a string specifying the name of the class where the type of the method return value is defined.

The "attributes" field

The optional field. The array of strings that specifies the properties of the method return value.

Possible return value attributes

#

Attribute name

Attribute description

1

not_apply_to_child_class

The annotation does not apply to the method if its return value type is a child of the annotated type.

2

always_taint

The method returns tainted data.

3

transfer_annotations_from_caller

If the caller object has an annotation, it will be propagated to the method return value.

Constructor annotations

Note. The constructor annotation object must include at least one optional field.

The constructor annotation object consists of the following fields:

The "type" field

The mandatory field. It takes a string with the ctor value.

The "namespace_name" field

The mandatory field. It takes a string specifying the name of the namespace that contains the constructor.

The "type_name" field

The mandatory field. It takes a string specifying the name of the class where the constructor is defined.

The "attributes" field

The optional field. The array of strings that specifies the properties of an entity.

Possible attributes for constructors

#

Attribute name

Attribute description

1

not_apply_to_child_class

The annotation does not apply to child implementations of the annotated constructor.

2

create_taint_object

The object created by the constructor is taint.

The "params" field

The optional field. This field is described in the "Parameter annotations" section.

Property annotations

The property annotation object consists of the following fields:

The "type" field

The mandatory field. It takes a string with the property value.

The "namespace_name" field

The mandatory field. It takes a string specifying the name of the namespace that contains the property.

The "type_name" field

The mandatory field. It takes a string specifying the name of the class where the property is defined.

The "attributes" field

The optional field. The array of strings that specifies the properties of an entity.

Possible property attributes

Note: Each taint sink attribute has a link to the diagnostic rule.

#

Attribute name

Attribute description

1

not_apply_to_child_class

The annotation does not apply when accessing the annotated property of a child class object.

2

transfer_annotation_to_return_value

If the caller object has an annotation, it will be propagated to the return value.

3

transfer_annotation_to_caller

When a value is assigned to a property, the annotations of that value are applied to the property object that calls it.

4

return_taint

The property returns tainted data.

5

sql_injection_target

Writing tainted data to this property leads to SQL injection (V5608).

6

path_traversal_target

Writing tainted data to this property leads to a path traversal vulnerability (V5609).

7

xss_injection_target

Writing tainted data to this property leads to XSS injection (V5610).

8

insecure_deserialization_target

Writing tainted data to this property leads to insecure deserialization (V5611).

9

command_injection_target

Writing tainted data to this property leads to command injection (V5616).

10

ssrf_target

Writing tainted data to this property leads to server-side request forgery (V5618).

11

log_injection_target

Writing tainted data to this property leads to log injection (V5619).

12

ldapi_injection_target

Writing tainted data to this property leads to LDAP injection (V5620).

13

xpath_injection_target

Writing tainted data to this property leads to XPath injection (V5622).

14

open_redirect_target

Writing tainted data to this property leads to an open redirect vulnerability (V5623).

15

configuration_attack_target

Writing tainted data to this property leads to a configuration attack (5624).

16

nosql_injection_target

Writing tainted data to this property leads to NoSQL injection (5627).

17

redos_target

Writing tainted data to this property leads to a ReDoS (V5626).

18

zipslip_target

Writing tainted data to this property leads to a Zip Slip vulnerability (V5628).

Parameter annotations

Note 1. A parameter annotation object can only reside in the 'params' array, method annotation object or constructor.

Note 2. The parameter annotation object must either contain the 'namespace_name' and 'type_name' fields, or both fields must be absent (or set to null).

The parameter annotation object consists of the following fields:

The "namespace_name" field

The mandatory field. It takes a string specifying the name of the namespace that contains the parameter type.

The "type_name" field

The mandatory field. It takes a string specifying the name of the class where the parameter type is defined.

The "attributes" field

The optional field. The array of strings that specifies the properties of an entity.

Possible parameter attributes

Note. Each taint sink and taint validation attribute have a link to the diagnostic rule.

#

Attribute name

Attribute description

1

ignore_current_and_next

The current and next parameters will not be considered when selecting the annotation; only the last argument can have this annotation.

2

transfer_annotation_to_return_value

If the parameter has an annotation, it will be propagated to the method return value.

3

object_creation_infector

Tainting of a newly created object occurs through this parameter (applicable only for constructors).

4

sql_injection_target

Passing tainted data to this parameter leads to SQL injection (V5608).

5

sql_injection_validation

Calling the method resets the SQL injection taint status for this parameter (V5608).

6

path_traversal_target

Passing tainted data to this parameter leads to a path traversal vulnerability (V5609).

7

path_traversal_validation

Calling the method resets the path traversal taint status for this parameter (V5609).

8

xss_injection_target

Passing tainted data to this parameter leads to XSS Injection (V5610).

9

xss_injection_validation

Calling the method resets the XSS Injection taint status for this parameter (V5610).

10

insecure_deserialization_target

Passing tainted data to this parameter leads to insecure deserialization (V5611).

11

insecure_deserialization_validation

Calling the method resets the insecure deserialization taint status for this parameter (V5611).

12

command_injection_target

Passing tainted data to this parameter leads to command injection (V5616).

13

command_injection_validation

Calling the method resets the command injection taint status for this parameter (V5616).

14

xml_source_to_parse

The parameter is the XML source that will be parsed. It can be the XML file itself, the path to the file, the XML file stream, a parser that includes the XML file stream, and so on (V5614, V5615).

15

transfer_xml_settings_to_return

It passes the XML parser settings from this argument to the return value (V5614, V5615).

16

ssrf_target

Passing tainted data to this parameter leads to server-side request forgery (V5618).

17

ssrf_validation

Calling the method resets the server-side request forgery taint status for this parameter (V5618).

18

log_injection_target

Passing tainted data to this parameter leads to log injection (V5619).

19

log_injection_validation

Calling the method resets the log injection taint status for this parameter (V5619).

20

ldapi_injection_target

Passing tainted data to this parameter leads to LDAP injection (V5620).

21

ldapi_injection_validation

Calling the method resets the LDAP injection taint status for this parameter (V5620).

22

xpath_injection_target

Passing tainted data to this parameter leads to XPath injection (V5622).

23

xpath_injection_validation

Calling the method resets the XPath injection taint status for this parameter (V5622).

24

open_redirect_target

Passing tainted data to this parameter leads to an open redirect vulnerability (V5623).

25

open_redirect_validation

Calling the method resets the open redirect taint status for this parameter (V5623).

26

configuration_attack_target

Passing tainted data to this parameter leads to a configuration attack (5624).

27

configuration_attack_validation

Calling the method resets the configuration attack taint status for this parameter (5624).

28

nosql_injection_target

Passing tainted data to this parameter leads to NoSQL injection (5627).

29

nosql_injection_validation

Calling the method resets the NoSQL injection taint status for this parameter (V5627).

30

redos_target

A string that is parsed using a regular expression. Passing tainted data to this parameter leads to a ReDoS (V5626).

31

redos_validation

Calling the method resets the ReDoS taint status for this parameter (V5626).

32

zipslip_target

A string that can be used as a path to extract a file from the archive. Passing tainted data to this parameter leads to a Zip Slip vulnerability (V5628).

33

zipslip_validation

Calling the method resets the Zip Slip taint status for this parameter (V5628).

34

regex

The parameter is a regular expression.

Ignoring the parameter type

To ignore the type of a parameter, do not specify the 'namespace_name' and 'type_name', or set both fields to null.

JSON Schema

JSON Schema is included in the distribution kit or can be accessed via the link.

Examples:

Method annotation

Look at the method:

namespace MyNamespace
{
  public class MyClass
  {
    public string GetUserInput()
    {
      ....
    }
  }
}

Assume this method returns user input that may include tainted data. An annotation explaining this for the analyzer would be as follows:

{
  "version": 1,
  "language": "csharp",
  "annotations": [
    {
      "type": "method",
      "namespace_name": "MyNamespace",
      "type_name": "MyClass",
      "method_name": "GetUserInput",
      "returns": {
        "attributes": [ "always_taint" ]
      }
    }
  ]
}

Constructor annotation

Look at the constructor:

namespace MyNamespace
{
  public class MyClass
  {
    public MyClass()
    {
      ....
    }
  }
}

Assume this constructor creates an object that may contain tainted data. An annotation explaining this for the analyzer would be as follows:

{
  "version": 1,
  "language": "csharp",
  "annotations": [
    {
      "type": "ctor",
      "namespace_name": "MyNamespace",
      "type_name": "MyClass",
      "attributes": [ "create_taint_object" ]
    }
  ]
}

Property annotation

Look at the property:

namespace MyNamespace
{
  public class MyClass
  {
    public string UserInput 
    {
      get
      {
        ....
      }
    }
  }
}

Assume this property returns user input that may include tainted data. An annotation explaining this for the analyzer would be as follows:

{
  "version": 1,
  "language": "csharp",
  "annotations": [
    {
      "type": "property",
      "namespace_name": "MyNamespace",
      "type_name": "MyClass",
      "property_name": "UserInput",
      "attributes": [ "return_taint" ]
    }
  ]
}

Annotation for a method/constructor where the parameter type is disregarded

Note. A method annotation is provided as an example. We can ignore the parameter type in the same way by not specifying 'type_name' and 'namespace_name' in the parameter annotation.

Here are two overloads of the 'GetUserInput' method:

namespace MyNamespace
{
  public class MyClass
  {
    public string GetUserInput(string str)
    {
      ....
    }

    public string GetUserInput(int index)
    {
      ....
    }
  }
}

Assume this method returns user input that may include tainted data, regardless of the parameter type. An annotation explaining this for the analyzer would be as follows:

{
  "version": 1,
  "language": "csharp",
  "annotations": [
    {
      "type": "method",
      "namespace_name": "MyNamespace",
      "type_name": "MyClass",
      "method_name": "GetUserInput",
      "params": [
        { }
      ],
      "returns": {
        "attributes": [ "always_taint" ]
      }
    }
  ]
}

In this case, there is no annotation for the first parameter. Additionally, when selecting a method annotation, the type of the first parameter is not important. As a result, the parameter annotation is represented by an empty object.

Annotation for a method or constructor that disregards certain parameters

Note. A method annotation is provided as an example. We can ignore the parameter type in the same way by using the 'ignore_current_and_next' annotation.

Here are two overloads of the 'GetUserInput' method:

namespace MyNamespace
{
  public class MyClass
  {
    public string GetUserInput(string str)
    {
      ....
    }

    public string GetUserInput(string str, bool flag1, bool flag2)
    {
      ....
    }
  }
}

Assume this method returns user input that may contain tainted data when an overload with one or more parameters. Additionally, if tainted data is passed to the first parameter, it will result in SQL injection. An annotation explaining this for the analyzer would be as follows:

{
  "version": 1,
  "language": "csharp",
  "annotations": [
    {
      "type": "method",
      "namespace_name": "MyNamespace",
      "type_name": "MyClass",
      "method_name": "GetUserInput",
      "params": [
        {
          "namespace_name": "System",
          "type_name": "String",
          "attributes": [ "sql_injection_target" ]
        },
        {
          "attributes": [ "ignore_current_and_next" ]
        }
      ],
      "returns": {
        "attributes": [ "always_taint" ]
      }
    }
  ]
}

There is the 'ignore_current_and_next' annotation for the second parameter. It enables us to disregard the number of parameters (including the annotated one) when processing the annotation.