All Collections
UpGuard API
How to retrieve risks detected for a vendor using the UpGuard API
How to retrieve risks detected for a vendor using the UpGuard API

Retrieve risks detected for a vendor through the command line by interfacing with the UpGuard API.

Caitlin Postal avatar
Written by Caitlin Postal
Updated over a week ago

When evaluating your cybersecurity posture, it's critical to assess your software supply chain and what new risks might be introduced by a vendor you are working with. As you perform your supplier risk assessment with UpGuard Vendor Risk, you'll identify specific risks for vendor remediation.

You can review a vendor's risks with the Portfolio Risk Profile module within the UpGuard platform, and you can retrieve a list of risks in the command line when using the UpGuard API.

In this tutorial, you will retrieve risks detected for a single vendor through the command line. You can choose from the provided options to interface with the UpGuard API through curl or Python. Finally, you will evaluate different options for using the data for your third-party risk management needs.

Prerequisites

Option 1 — Using curl to retrieve risks detected for a vendor

The curl command returns information from the internet in your command line terminal. By adding various options, you can customize what information is retrieved. In this section, you will run curl against the UpGuard API to authenticate with your UpGuard account and export information for the vendors you are currently monitoring.

To follow this tutorial with curl, you will need these additional prerequisites:

  • curl installed on your machine.

  • jq, a command-line JSON processing tool, installed on your machine.

Step 1 — Retrieving a list of risks detected for a specific vendor

In this step, you will run a curl command to retrieve the active risks detected for a specific vendor directly within the command line.

Open a terminal window and set the API key, providing the unique alphanumeric string for your personal API key where the sample below reads your_api_key:

$ API_KEY=your_api_key

Setting the API_KEY variable ensures that you can call it directly in future commands without providing the unique key in every command.

Run curl to retrieve information from UpGuard:

$ curl --request GET \
--header "Authorization: $API_KEY" \
--url "https://cyber-risk.upguard.com/api/public/risks/vendors?primary_hostname=example.com"

You run a GET request that will authenticate using your API variable and retrieve information from the /risks/vendors path for the vendor specified by the primary_hostname parameter. This example retrieves information for example.com, but you can supply a different vendor domain.

You'll receive a comma-separated value response similar to the following (this output has been truncated for brevity with IP addresses and domains redacted):

{"risks":[{"id":"exposed_service:Remote Desktop","finding":"'Remote Desktop' port open","risk":"Unnecessary open ports","description":"The 'Remote Desktop' service is running and exposed to the internet. The configuration of the server should be reviewed and unnecessary ports closed.","severity":"critical","category":"network_sec","firstDetected":"2023-01-29T19:24:07.398956Z","hostnames":["ip_address_here","domain_address_here"],"riskType":"exposed_service","riskSubtype":"Remote Desktop"}, ... ]}

The example provided lists only one risk but your output will likely return multiple.

To retrieve a more readable array, pipe the command through jq:

$ curl --request GET \
--header "Authorization: $API_KEY" \
--url "https://cyber-risk.upguard.com/api/public/risks/vendors?primary_hostname=example.com" \
| jq

This command may take some time to complete. When it does, the output will be easier to read (the example is truncated and redacted):

{
  "risks": [
    {
      "id": "exposed_service:Remote Desktop",
      "finding": "'Remote Desktop' port open",
      "risk": "Unnecessary open ports",
      "description": "The 'Remote Desktop' service is running and exposed to the internet. The configuration of the server should be reviewed and unnecessary ports closed.",
      "severity": "critical",
      "category": "network_sec",
      "firstDetected": "2023-01-29T19:24:07.398956Z",
      "hostnames": [
        "ip_address_here",
        "domain_address_here"
      ],
      "riskType": "exposed_service",
      "riskSubtype": "Remote Desktop"
    },
    ...
  ]
}

You can optionally set a minimum severity parameter to return only the risks that meet or surpass the severity threshold. Append the min_severity parameter with the & operator and specify the severity value from info, low, medium, high, or critical. This example retrieves critical risks detected for example.com:

$ curl --request GET \
--header "Authorization: $API_KEY" \
--url "https://cyber-risk.upguard.com/api/public/risks/vendors?primary_hostname=example.com&min_severity=critical"

You'll receive a similar output but with only those risks deemed critical. The output will return as a CSV format, but you can optionally pipe it through jq for a more readable format.

Once you have a list of risks, you can retrieve details for individual risks using the method described in Step 2 of our tutorial on How to get risks detected for your account.

To coordinate risk remediation with a vendor, you can also retrieve a list of risks introduced or resolved for a vendor's domains and IPs between two dates, which you will do next.

Step 2 — Retrieving a vendor's risk changes

As you evaluate your vendor risk threshold, it's important to know when new risks are introduced to your supply chain and when existing risks are resolved such that they are no longer a problem. You can review this information with the Vendor Risk module in UpGuard.

In this step, you will retrieve this information programmatically with the UpGuard API, evaluating the risk profile for a given vendor between two days.

Note: The maximum allowed interval for this type of API call is 30 days.

There are three query parameters to provide when retrieving the risk changes:

  • vendor_primary_hostname: the primary domain for the vendor.

  • start_date: an RFC 3339 timestamp to use as the starting date.

  • end_date: an RFC 3339 timestamp to use as the final date; if omitted, the latest risks will be returned.

Set the GET request for the /risk/vendors/diff path and supply the necessary parameters. This example uses example.com and the first 30 days of 2023:

$ curl --request GET \
--header "Authorization: $API_KEY" \
--url "https://cyber-risk.upguard.com/api/public/risks/vendors/diff?vendor_primary_hostname=example.com&start_date=2023-01-01T08:00:00Z&end_date=2023-01-31T08:00:00Z"

For the RFC 3339 format, you will need to provide a full timestamp with date and time. In the example provided, the T character indicates the shift from date to time and the Z character indicates the UTC time zone.

You'll receive a CSV output that you can optionally pipe the output through jq for a more readable format.

The sample output provided has been truncated to one set of risks in groupID with the domains and IP addresses redacted:

{
  "risksIntroduced": [
    {
      "groupID": "domain",
      "name": "Domain at risk of being hijacked",
      "highestSeverity": 4,
      "highestSeverityName": "high",
      "diffs": [
        {
          "id": "domain_expiry",
          "group": "domain",
          "category": "brand_protect",
          "description": "The domain expires soon, and anyone may be able to purchase  it when it expires. You should renew your domain registration ASAP.",
          "severity": 3,
          "severityName": "medium",
          "name": "Domain expires soon",
          "cloudscanDiffs": [
            {
              "hostname": "domain_example_1",
              "property": "Domain > Expires On",
              "expected": "[does not expire in next 30 days]",
              "dateA": "2023-01-17T05:06:59.754270Z",
              "dateB": "2023-01-19T03:28:45.507276Z",
              "statusA": "PASS",
              "statusB": "FAIL",
              "metaValueA": "2023-02-17T23:59:59.000Z",
              "metaValueB": "2023-02-17T23:59:59.000Z"
            },
            ...
          ],
          "vendorDiff": null,
          "riskType": "domain_expiry",
          "riskSubtype": ""
        },
        ...
      ]
    },
    ...
  ],
 "risksResolved": [
    {
      "groupID": "clickjacking",
      "name": "Vulnerable to clickjacking attacks",
      "highestSeverity": 3,
      "highestSeverityName": "medium",
      "diffs": [
        {
          "id": "x_frame_options_header",
          "group": "clickjacking",
          "category": "website_sec",
          "description": "Browsers may display this website's content in frames. This can lead to clickjacking attacks.",
          "severity": 3,
          "severityName": "medium",
          "name": "X-Frame-Options is not deny or sameorigin (Provisional)",
          "cloudscanDiffs": [
            {
              "hostname": "domain_example_2",
              "property": "Headers > x-frame-options",
              "expected": "[deny or sameorigin]",
              "dateA": "2023-01-14T11:12:19.869642Z",
              "dateB": "2023-01-31T08:00:00.000000Z",
              "statusA": "FAIL",
              "statusB": "UNKNOWN",
              "metaValueA": "ALLOWALL",
              "metaValueB": ""
            },
            ...
          ],
          "vendorDiff": null,
          "riskType": "x_frame_options_header",
          "riskSubtype": ""
        }
      ]
    },
    ...
}

The sample output begins with an array for new risks introduced during the specified time interval, categorized by the groupID class. The subsequent array summarizes the risks that were resolved during that interval, also categorized by the groupID class.

For both arrays, you'll receive information about the risk type and severity, as well as the initial and updated status during the interval specified in the GET request. For example, the upcoming domain expiration for domain_example_1 was first noted on 2023-01-17 and was not at risk. However, when reviewed again on 2023-01-19, it was at risk. You can use the dateA and dateB window with the statusA and statusB attributes to assess the risk status for both newly introduced and recently resolved risks.

If you opt to retrieve this information by using the UpGuard API, we recommend incorporating the output into your existing analysis scripting process. Programmatic information retrieval like this example is well-suited to complex data analysis using tools like Python. The following option details how to retrieve this information with a Python script.

Option 2 — Using Python to retrieve risks detected for a vendor

Python enables you to automate tasks with custom scripts that can complete complex actions consistently. In this section, you will build two short scripts to retrieve vendor information from UpGuard, but you can combine this script with other Python syntax to accommodate your larger needs.

To follow this guide with Python, you will need these additional prerequisites:

  • Python installed on your machine.

  • A Python virtual environment.

Step 1 — Activating your Python environment

In this section, you will activate a Python virtual environment that was set up with the venv module. You can also use an alternative virtual environment, like PyCharm or Miniconda.

You can create as many virtual programming environments as you wish, which will keep your scripts in distinct folders. This tutorial will use a directory named environments. In your terminal, move to that directory:

$ cd environments

Activate the test environment, replacing test_env with the name you supplied during the prerequisites:

$ source test_env/bin/activate

The name of your test environment will appear as a prefix for your terminal prompt. In this example, the name is test_env:

(test_env) your_user@your_machine_name~/your_path 

With the environment running, you can now create and run a script to retrieve vendor information.

Step 2 — Retrieving a list of risks detected for a specific vendor

Once you have a list of risks, you can retrieve details for individual risks using the method described in Step 2 of our tutorial on How to retrieve risks detected for your account using the UpGuard API.

First, use your preferred editor to create the script file. This example uses nano:

$ nano getVendorRisks.py

Add the following script, which will interface with the UpGuard API to return information about monitored vendors for your account:

import requests

api_key = "your_api_key" headers = { "Authorization": api_key } params = { 'primary_hostname': 'vendor_domain', } base_url = "https://cyber-risk.upguard.com/api/public"

response = requests.get(base_url + '/risks/vendors', params=params, headers=headers) print(response.status_code) print(response.text)

First, you import the requests library, which you will use to send a GET request.

Then, you set three variables that will be used in the script. Be sure to update your_api_key with the alphanumeric string associated with your account so that the api_key variable can be called to authorize your request. Update vendor_domain with the domain of the vendor whose risks you wish to retrieve.

Note: For an added layer of security, you can set your API key in a .env file in the root directory of your Python environment and call that file within the script using a package such as python-dotenv, which will ensure that your API key is not stored in the script. We have not evaluated the security of external packages like python-dotenv, and you should consult with your security team regarding the introduction of any new tooling.

Finally, you define the GET request with three arguments: the base_url endpoint directing to the /risks path, the specific vendor as defined by your params variable, and authorization using your API key as a headers variable. The response will be stored in the response variable. The status_code and text attributes of the response object will be printed to your terminal window.

Save and close the file, then run the script:

python getVendorRisks.py

You'll receive a comma-separated value response similar to the following (this output has been truncated for brevity with IP addresses and domains redacted):

{"risks":[{"id":"exposed_service:Remote Desktop","finding":"'Remote Desktop' port open","risk":"Unnecessary open ports","description":"The 'Remote Desktop' service is running and exposed to the internet. The configuration of the server should be reviewed and unnecessary ports closed.","severity":"critical","category":"network_sec","firstDetected":"2023-01-29T19:24:07.398956Z","hostnames":["ip_address_here","domain_address_here"],"riskType":"exposed_service","riskSubtype":"Remote Desktop"}, ... ]}

The array provides details for the risks detected for the vendor you specified. The sample output provides details for only one risk but your response will likely include more. The first line returns the status code for the ping. This output returns 200 for a successful request

Note: If you receive a 422 error response, review the error message to update your parameters. A 500 error response returns when a system error occurs. In that case, review the error message and try again later.

To pretty-print the array or to save the output to a new file, you can follow the same methods as detailed in the Python section of our tutorial on How to retrieve risks detected for your account using the UpGuard API.

To coordinate risk remediation with a vendor, you can also retrieve a list of risks introduced or resolved for a vendor's domains and IPs between two dates. You can modify the existing script, providing the additional parameters necessary for this type of request as detailed in the section on using curl to retrieve risk changes.

Evaluating the risk details

For each individual risk, the response details will include an array containing some of available attribute responses. You can use these details to coordinate your risk remediation plan and otherwise provision security updates to your supply chain. This section will explain the aspects of the response schema, using the 'Remote Desktop' port open finding as the example risk.

The response schema may include any of the following 12 attributes when retrieving all active risks for your account:

  • category returns a string containing the risk category from UpGuard's six risk categories.

  • description provides a long description of the risk.

  • finding provides a short description of the finding.

  • firstDetected returns a string with the date and time that the risk was first detected for your account.

  • hostnameMeta may return a map for each hostname if there is metadata available for that hostname.

  • hostnames returns an array with hostnames where the risk was detected.

  • id provides the specific risk identifier.

  • risk returns a short description of the risk.

  • riskSubtype returns a subtype of the risk when verified, but will be empty if the risk has no subtype.

  • riskType specifies the type of risk from the full riskSubtype string.

  • risk_waivers supplies an array of risk waivers applicable to this risk (if any) and has its own set of attributes relevant to the risk waiver.

  • severity lists the severity of the risk.

For example, the following output indicates the remote desktop port risk when it appears in a list of risks:

{
  "risks":[
    {
      "id":"exposed_service:Remote Desktop",
      "finding":"'Remote Desktop' port open",
      "risk":"Unnecessary open ports",
      "description":"The 'Remote Desktop' service is running and exposed to the internet. The configuration of the server should be reviewed and unnecessary ports closed.",
      "severity":"critical",
      "category":"network_sec",
      "firstDetected":"2023-01-29T19:24:07.398956Z",
      "hostnames":["ip_address_here","domain_address_here"],
      "riskType":"exposed_service",
      "riskSubtype":"Remote Desktop"
    }, 
    ...
  ]
}

This particular risk is a critical severity vulnerability in the Network Security category and impacts a specific hostname. It was first detected in January 2023. The resulting recommendation would be to review access to the IP address and close any ports that do not need to be open.

Retrieving details for specific risks can support your risk remediation planning and organizational processes.

Further reading

As you identify risks related to your vendors' security, you can communicate with your vendors regarding risk remediation in the UpGuard platform:

Now that you can retrieve risk information for vendors, you can use that information for your organization's security needs. Read the following articles for more information:

Did this answer your question?