Share with Your Network
Recently some developers have been asking about vulnerability management (VM) custom fields attached to vulnerabilities. In attempting to answer their questions, it was discovered the API documentation was incorrect. Now the documentation has been fixed, I thought a blog on custom fields would be helpful.
If you’re curious about why this is Part Two, it is because both Part One and Part Two are about metadata. Part One is about Asset metadata while Part Two is about vulnerability metadata.
Custom fields are additional metadata to vulnerabilities. They add context. For example, when creating a CISA risk meter, the CISA custom field was created to indicate the vulnerability was on the CISA list. This blog will discuss how to search for and update custom fields with APIs. It will also discuss code that lists unique custom fields and their values.
Custom Field Search
To search for a custom field, the “Search Vulnerabilities” API is used. The query parameter
custom_fields is used in the following manner:
If you want to search for more than one custom field, I recommend:
custom_fields: with the custom field and
 after the custom field is required. Unfortunately, wildcarding is not allowed. Some developers might think that this query parameter is poorly defined. I would agree, and we know about it, but we’re stuck with it for now.
Here are two code examples:
And in search_custom_fields.py:
The script search_custom_fields.py is provided in the custom_fields directory of Kenna’s blog_samples repo as a simple custom field search script. It takes two command line parameters, custom_field name, and custom_field value, and returns the basic information on the vulnerabilities that contain the desired custom field and the custom field value. Feel free to enhance.
Custom Field Update
Let’s say you have a custom field,
risk_accepted_expiration_date. You want a user interface or a small script to update the risk accepted expiration date. To do this you will need to use the “Update Vulnerabilities” API. It can be used to update custom fields of one vulnerability. Here is an example below from update_custom_field.py:
Since this is an update, the custom field information is in the HTTP request body. To update a custom field, the custom field ID is required along with the new value to update with. To obtain the custom field ID, invoke the List or Search Vulnerabilities APIs.
Custom Field Bulk Update
To update a custom field for a list of vulnerabilities, the “Bulk Update Vulnerabilities” API is used. This was discussed in the “How to Create a CISA Risk Meter” blog, section “Bulk Vulnerabilities Update,” but I’m going to review it here. The HTTP request body is the same when it comes to custom fields; however, now
vulnerability_ids to be updated are included in the HTTP request body. Here is an example from build_cisa_risk_meter.py:
Again the custom field ID along with the new custom field value is required.
List Unique Custom Fields
Saving the largest topic for last. One issue with using custom fields is there is no way to obtain a list of custom fields being used for all your vulnerabilities. Are they still valid? What values are you using? I wrote the script, blog_list_custom_fields.py, to create a list of custom fields with a usage count, and custom field values, and written to a CSV file.
Let’s look at the script’s data structures. There is a class,
Custom_Field that contains the custom field name, ID, unique values, and count. It contains methods to add new custom field values, return the values, and return the number of values. Looking at it, you will notice that the code checks if the value is
The reason is once a custom field is defined, it is attached to all vulnerabilities with a null value. This script is only interested in non-null values (
None in python). If the value is not, it is set for this vulnerability and therefore placed in the values array provided that it is not already in the array.
The other data structure is the dictionary,
unique_custom_fields. The custom field name is the key and it maps to an
Custom_Field object. It is passed by reference to the appropriate functions.
Obtaining Vulnerability Information
First, the script does a vulnerability export. This is very similar to an asset export. This was covered in the blog “Unique Asset Tags – Part 1“. The only difference is that
export_settings is set to
vulnerability instead of
asset for the “Request Data Export” API.
Reads the JSONL file line by line converting each line to a JSON dictionary. Each line is a vulnerability. If there are
custom_fields in the vulnerability, then further processing is required in
process_custom_fields(). A dot is produced for every 1000 vulnerabilities processed. Hopefully, this status won’t keep you hanging and indicates processing is begin performed.
This function decides in the custom field is unique. It does this by checking if the custom field name key is in
unique_custom_fields (line 232).
If the custom field is in the dictionary, then the value is added to the custom field by calling
append_new_value() in line 237, else a new custom field entry is created by calling
append_custom_field() in line 239.
This is the function where a new
Custom_Field object is created and appended to the
As a reminder, the custom field name is used as a key.
Finally, we get to the function that writes the unique custom field information to the CSV file,
There are two types of rows, one for null custom field values and one for non-null custom field values.
- null value row contains: custom field name, ID, and a zero count. (line 273)
- a non-null row contains: custom field name, ID, non-zero count, number of unique values, and the unique values. (line 275-276)
If the count is zero, that implies that no one is currently using the custom field. It could be time to remove the unused custom field.
Above is an Excel representation of the
unique_custom_fields.csv. As you can see the spreadsheet has “Custom Field,” “Custom Field ID,” “Field Count,” “Value Count,” and “Custom Field Values.” If the “Field Count” is zero, the custom field is currently not being used. “Custom Field Values is a comma separate string; for example, “Bad, good, extract, excellent” are contained in one cell.
After reading this blog, my hope is as a developer, you will know how to work with VM custom fields and the code examples will inspire you to write your own scripts. The new code mentioned in this blog is located in Kenna Security’s Github blog_samples repository under the python/custom_fields directory.
Until next time,