All Collections
UpGuard API
How to retrieve risks detected for your account using the UpGuard API
How to retrieve risks detected for your account using the UpGuard API

Retrieve risks details for your account through the command line by interfacing with the UpGuard API.

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

Before you can coordinate best practices for your organization's security plan, you need to know the full extent of external risks facing your organization but identifying these risks manually can be time-consuming and labor-intensive. With UpGuard BreachSight, you gain insight to your organization's risk profile and the cybersecurity risk factors in your publicly accessible information.

Using the UpGuard API, you can retrieve available risks within the platform, including a list of active risks detected for your account. You can always evaluate your risk profile directly within the UpGuard platform. With the UpGuard API, you can retrieve the same information from the command line and incorporate it into your security hardening process.

In this guide, you will retrieve only those risks detected for your account. You will choose from the provided options to interface with the UpGuard API through curl, Python, or Ruby.

Prerequisites

Option 1 — Using curl to retrieve risks detected for your account

You can use the curl command to retrieve information from the internet directly within your command line terminal. You supply the options necessary to retrieve specific information against an existing URL. In this option, you will run curl against the UpGuard API to authenticate with your UpGuard account and retrieve risk details for your account.

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 all risks for your account

In this step, you will run a curl command to retrieve your account's active risks 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 pull information from your account:

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

You set a custom header with the --header flag, specifying that your terminal is authorized with the API key you provided earlier. Because you have already set the $API_KEY variable with your unique key, you call the variable directly.

You then provide an endpoint within the UpGuard platform to generate a response. The /risks path will return a list of risks detected for your account, but you can use any of the options available in our API documentation to test this feature. The base URL for all public endpoints is https://cyber-risk.upguard.com/api/public.

You'll receive a response in the form of a comma-separated value (CSV) list with all of the vendors you currently monitor and a variety of information related to each risk, which you can then apply transformations to sort. Your output may be quite lengthy.

You'll receive an output similar to this example but with risks for your account:

{"risks":[{"id":"end_of_life_product_provisional:cpe:/a:php:php","finding":"End-of-life version of PHP detected (Provisional)","risk":"Vulnerabilities","description":"The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.","severity":"high","category":"website_sec","firstDetected":"2023-05-01T06:29:35.819047Z","hostnames":["warning.be"],"riskType":"end_of_life_product_provisional","riskSubtype":"cpe:/a:php:php"}, ... }

You can also pipe the output through jq to pretty-print the response in a more readable format:

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

The CSV format will be parsed into a JSON array:

{
  "risks": [
    {
      "id": "end_of_life_product_provisional:cpe:/a:php:php",
      "finding": "End-of-life version of PHP detected (Provisional)",
      "risk": "Vulnerabilities",
      "description": "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
      "severity": "high",
      "category": "website_sec",
      "firstDetected": "2023-05-01T06:29:35.819047Z",
      "hostnames": [
        "warning.be"
      ],
      "riskType": "end_of_life_product_provisional",
      "riskSubtype": "cpe:/a:php:php"
    },
...
  ]
}

The PHP end-of-life finding is an example for one risk that might be associated with accounts. Your list of risks will differ.

Returning all risks detected for your account is a crucial step in planning your security updates. If you only want to retrieve information for a specific risk in the list, you can supply additional parameters, which you will do next.

Step 2 — Retrieving details for a specific risk

When you are coordinating your risk remediation plan, you may wish to evaluate a specific risk. The UpGuard API provides a distinct path for calling specific risk details, so you will modify the curl command in this step to retrieve information for only one risk. This step will proceed with the end-of-life PHP vulnerability returned in the previous step.

First, note the id string for the given risk. The risk_id for the sample PHP risk is end_of_life_product_provisional:cpe:/a:php:php.

You'll be sending a request to the available risks endpoint (/available_risks/v2) and appending the specific risk ID to the URL:

$ curl --request GET \
--header "Authorization: $API_KEY" \
--url "https://cyber-risk.upguard.com/api/public/available_risks/risk?risk_id=end_of_life_product_provisional:cpe:/a:php:php"

You've revised the URL to point to the available risks metadata and, more specifically, to an individual risk ID.

If you don't use jq to transform the data, it will return in a comma-separated format. If you pipe the output through jq, you will receive a readable response in your terminal:

{
  "id": "end_of_life_product_provisional:cpe:/a:php:php",
  "group": "vulns",
  "risk": "Vulnerabilities",
  "generic": false,
  "severity": "high",
  "category": "website_sec",
  "finding": "End-of-life version of PHP detected (Provisional)",
  "description": "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
  "remediation": "Review the product and plan the necessary updates.",
  "riskType": "end_of_life_product_provisional",
  "riskSubtype": "cpe:/a:php:php"
}

The remediation attribute provides information about the type of risk and a recommendation for risk remediation, which may be beneficial as you plan your risk management process. For more information on each of the risk details, move section titled Evaluating risk details.

If you are interested in automating this GET request as a Python or Ruby script, follow the procedure in the next section.

Option 2 — Using Python to retrieve risks detected for your account

With Python, you can work quickly and automate tasks like GET requests. Python's precise syntax enables you to create custom scripts that can complete complex actions consistently. As you evaluate risks and vulnerabilities in your software supply chain, you may want to build systems to complete tasks quickly and efficiently in a sequential order. In this section, you will build two short scripts to retrieve risk details from UpGuard, but you can combine this script with other Python syntax to accommodate your larger needs.

To follow this tutorial with Python, you will need Python installed on your machine with a virtual environment set up.

Step 1 — Activating your Python environment

In this step, 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 for your virtual environment:

$ 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 risk details.

Step 2 — Retrieving all risks with Python

In this step, you will create and run a Python script to retrieve the risks detected for your account.

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

$ nano getRisks.py

Add the script, supplying your API key where the example reads your_api_key:

import requests

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

response = requests.get(base_url + '/risks', 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.

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 two arguments: the base_url endpoint directing to the /risks path 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:

$ python3 getRisks.py

You'll receive a CSV response similar to this output but with risks detected for your account:

200
{"risks":[{"id":"end_of_life_product_provisional:cpe:/a:php:php","finding":"End-of-life version of PHP detected (Provisional)","risk":"Vulnerabilities","description":"The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.","severity":"high","category":"website_sec","firstDetected":"2023-05-01T06:29:35.819047Z","hostnames":["warning.be"],"riskType":"end_of_life_product_provisional","riskSubtype":"cpe:/a:php:php"}, ... ]}

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.

The subsequent array provides details for the risks detected for your account. The sample output provides details for only one risk but your response will likely include more.

To pretty-print the output, you'll update the Python script. Open the script file:

$ nano getRisks.py

You'll be modifying the response output to use the json module:

import requests
import json

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

response = requests.get(base_url + '/risks', headers=headers) formatted_string = json.dumps(response.json(), indent=4) print(response.status_code) print(formatted_string)

You add the json module to your import syntax. The variables and GET request remain as written, storing the response in a response variable.

You then modify the output as a formatted_string variable. You use the formatted_string variable to prettify the JSON output in a human-readable format. The json.dumps() function will apply a JSON transformation to the response output with an indentation of four spaces. You can set other formatting needs if you wish. When you print attributes of the response, you swap the text attribute for the new formatted string variable, which moves the response text into a JSON array.

Save and close the updated file, then run it:

$ python3 getRisks.py

You'll receive a newly formatted JSON array for the output:

200
{
    "risks": [
        {
            "id": "end_of_life_product_provisional:cpe:/a:php:php",
            "finding": "End-of-life version of PHP detected (Provisional)",
            "risk": "Vulnerabilities",
            "description": "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
            "severity": "high",
            "category": "website_sec",
            "firstDetected": "2023-05-01T06:29:35.819047Z",
            "hostnames": [
                "warning.be"
            ],
            "riskType": "end_of_life_product_provisional",
            "riskSubtype": "cpe:/a:php:php"
        },
        ...
    ]
}

To send the output to a new file, append the command with an output redirection to a file using the > operator:

$ python3 getRisks.py > getRisks.txt

With this redirection, the output will be saved to a file named getRisks.txt (but you can supply whatever file name you like) instead of displaying in your terminal. You can run cat to display the new file in the terminal in order to confirm the redirection, or you can access the file in your machine's document structure as needed.

Risk detection for your account follows the scanning protocols that UpGuard has in place, including port scanning and risk data collection, so you may opt to run a risk detection script periodically. Assessing risks detected on a regular cadence will ensure that you can prioritize according to your remediation process.

In this step, you retrieved information for all risks detected for your account. Next, you'll retrieve details for one specific risk by its risk identification label.

Step 3 — Retrieving details for a single risk with Python

If you know the risk id for a particular risk, you can retrieve the details quickly with a call to the UpGuard API. In this step, you'll retrieve information for the same sample risk that has been used throughout this guide: the PHP end-of-life provisional risk.

You'll create a new scripting file. Provide any name that you will remember; this example uses getOneRisk.py:

$ nano getOneRisk.py

You'll use the same script as in the previous step, updating it to include a parameter query and a different URL endpoint:

import requests

api_key = "your_api_key" headers = { "Authorization": api_key } params = {"risk_id": "end_of_life_product_provisional:cpe:/a:php:php" } base_url = "https://cyber-risk.upguard.com/api/public"

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

Be sure to supply your unique alphanumeric API key.

You add a new params variable with the risk_id query. In this example, you provide the string for the PHP end-of-life risk, but you can optionally supply a different risk_id string. You also update the GET request to call the /available_risks/risk path and include the params variable in the call.

Save and close the file, then run the script. You'll receive an output with the status_code followed by the risk details:

200
{"id":"end_of_life_product_provisional:cpe:/a:php:php","group":"vulns","risk":"Vulnerabilities","generic":false,"severity":"high","category":"website_sec","finding":"End-of-life version of PHP detected (Provisional)","description":"The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.","remediation":"Review the product and plan the necessary updates.","riskType":"end_of_life_product_provisional","riskSubtype":"cpe:/a:php:php"}

You can modify the file with the same adjustments as in the previous step in order to prettify the JSON output. You can also append the command with the redirection operator to save the output to a named file.

If you are interested in automating this GET request as a Ruby script, follow the procedure in the next section. Otherwise, proceed to the Evaluating risk details section for more information on the details that return.

Option 3 — Using Ruby to retrieve risks detected for your account

You can use Ruby to process data retrieved from the web. Like Python, Ruby can be helpful in automating tasks with a logical script. As you evaluate risks and vulnerabilities in your software supply chain, you may want to build systems to complete tasks quickly and efficiently in a sequential order. In this section, you will build two short scripts to retrieve risk details from UpGuard, but you can combine this script with other Ruby syntax to accommodate your larger needs.

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

  • Ruby installed on your machine.

  • Ruby gems installed on your machine: httparty, json, and pp.

Step 1 — Preparing your Ruby environment

Before writing scripts in Ruby, you should ensure that you have the necessary prerequisites. If you have confirmed that you have Ruby and the required modules on your machine, you can proceed to Step 2. Otherwise, follow the procedure in this section.

To begin, check if you have Ruby installed on your machine:

$ ruby -v

If Ruby is installed, you will receive an output with the version number, such as:

ruby 3.2.2

If Ruby is not installed, you will need to install it now.

For macOS, you can install Ruby with Homebrew:

$ brew install ruby

Note: macOS comes with a version of Ruby already installed. However, you will not be able to change anything with the pre-installed version, so you will not be able to install the required gems for this tutorial unless you install a separate version of Ruby. When you run brew install ruby, follow the recommended steps after installation to ensure that you can modify the new version.

For Linux or WSL, you can install Ruby with your preferred package manager. For example, you could use the apt package manager to install Ruby with the following command:

$ sudo apt install ruby-full

Confirm that you have installed Ruby:

$ ruby -v

You will now receive an output with the version number, such as:

ruby 3.2.2

Next, you will install the httparty and json gems. Gems package third-party Ruby libraries that empower you to create complex Ruby scripts.

Note: For macOS, ensure that you have installed a separate version of Ruby that you can modify. Otherwise you may receive a permissions error that you cannot write to the Ruby directory.

You can use the Ruby Gem installer for both httparty and json:

$ gem install httparty
$ gem install json

For each gem, you will receive a response in the terminal that the gem is being fetched and installed. To confirm the installations, you can the the command gem list to receive an output of all the Ruby gems that are installed locally on your machine.

Note: The pp gem comes packaged with Ruby. If you installed a fresh version of Ruby, you can run gem list to confirm that pp is available. Otherwise, run gem install pp to ensure it is available.

Now that you have Ruby and the necessary gems installed on your machine, you can now create the script to retrieve risk details.

Step 2 — Retrieving all risks with Ruby

In this step, you will create and run a Ruby script to retrieve the risks detected for your account.

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

$ nano getRisks.rb

Add the script, supplying your API key where the example reads your_api_key:

require 'httparty'
require 'json'
require 'pp'

$api_key = "your_api_key" $base_url = "https://cyber-risk.upguard.com/api/public"

response = HTTParty.get( "#{$base_url}/risks", :headers => { "Authorization" => $api_key } )

response = JSON.parse(response.body) pp response

First, you define the three gems that will be used in this script: - httparty to run the GET request. - json to parse the response output. - pp to pretty-print the output in a readable format.

Note: You can optionally omit the pp gem and provide a standard puts or print method to return the response output. If you make this adjustment, the output will return in a CSV format rather than a readable JSON array.

You then set two variables: one for your unique alphanumeric API key and one for the public API endpoint.

Next, you define the GET request to point to the /risks path on the endpoint, calling your API key to authorize the request.

Finally, you parse the response output and pretty-print it to your terminal.

Save and close the file, then run it:

$ ruby getRisks.rb

You'll receive a response similar to following (truncated for length):

{"risks"=>
   {"id"=>"end_of_life_product_provisional:cpe:/a:php:php",
    "finding"=>"End-of-life version of PHP detected (Provisional)",
    "risk"=>"Vulnerabilities",
    "description"=>
     "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
    "severity"=>"high",
    "category"=>"website_sec",
    "firstDetected"=>"2023-05-01T06:29:35.819047Z",
    "hostnames"=>["warning.be"],
    "riskType"=>"end_of_life_product_provisional",
    "riskSubtype"=>"cpe:/a:php:php"},
    }
    ...
}

Note: If you modify the line from pp to a puts or print method, your output will be in a CSV format.

Now that you can retrieve all risks for your account, you'll create another risk to return details for one specific risk.

Step 3 — Retrieving details for a single risk with Ruby

When you know the risk id for a particular risk, you can retrieve the details quickly with a call to the UpGuard API. In this step, you'll retrieve information for the same sample risk that has been used throughout this guide: the PHP end-of-life provisional risk.

You'll create a new scripting file. Provide any name that you will remember:

$ nano getOneRisk.rb

You'll use the same script as in the previous step, updating it to include a parameter query and a different URL endpoint:

require 'httparty'
require 'json'
require 'pp'

$api_key = "your_api_key" $base_url = "https://cyber-risk.upguard.com/api/public" $param = ("?risk_id=end_of_life_product_provisional:cpe:/a:php:php")response = HTTParty.get( "#{$base_url}/available_risks/risk" + $param, :headers => { "Authorization" => $api_key } )response = JSON.parse(response.body) pp response

You set the parameter and then call it in the GET request.

Save and close the file, then run it:

$ ruby getOneRisk.rb

You'll receive an output for the specified risk:

{"id"=>"end_of_life_product_provisional:cpe:/a:php:php",
 "group"=>"vulns",
 "risk"=>"Vulnerabilities",
 "generic"=>false,
 "severity"=>"high",
 "category"=>"website_sec",
 "finding"=>"End-of-life version of PHP detected (Provisional)",
 "description"=>
  "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
 "remediation"=>"Review the product and plan the necessary updates.",
 "riskType"=>"end_of_life_product_provisional",
 "riskSubtype"=>"cpe:/a:php:php"}

Note: The current Ruby script will output the data in a readable JSON array. You can optionally replace the pp method with a puts or print method, which will return the output in a CSV format.

You can redirect the output while running the script to save it to a new file, or you can update the script to save the response to a file.

The remediation attribute provides information about the type of risk and a recommendation for risk remediation, which may be beneficial as you plan your risk management process. In the next section, you will review the various attributes for details.

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 PHP end-of-life risk as the example risk.

The response schema may include any of the following 11 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.

  • 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 from pass, info, low, medium, high, or critical.

For example, the following output indicates the PHP end-of-life risk when it appears in a list of risks:

{
  "risks": [
    {
      "id": "end_of_life_product_provisional:cpe:/a:php:php",
      "finding": "End-of-life version of PHP detected (Provisional)",
      "risk": "Vulnerabilities",
      "description": "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
      "severity": "high",
      "category": "website_sec",
      "firstDetected": "2023-05-01T06:29:35.819047Z",
      "hostnames": [
        "warning.be"
      ],
      "riskType": "end_of_life_product_provisional",
      "riskSubtype": "cpe:/a:php:php"
    },
...
  ]
}

This particular risk is a high severity vulnerability in the Website Security category and impacts the sample hostname warning.be. The resulting recommendation would be to assess and update the PHP version associated with that domain.

When retrieving only one specific risk, the response schema may include these additional attributes:

  • generic returns a boolean response indicating whether the risk is a generic risk.

  • group returns a string with the risk grouping.

  • remediation returns a recommendation for how to mitigate the risk vulnerabilities.

Retrieving details for only the specific sample risk will return an output like the following:

{
  "id": "end_of_life_product_provisional:cpe:/a:php:php",
  "group": "vulns",
  "risk": "Vulnerabilities",
  "generic": false,
  "severity": "high",
  "category": "website_sec",
  "finding": "End-of-life version of PHP detected (Provisional)",
  "description": "The detected version of PHP is end of life. The product will likely not receive security updates from the vendor moving forward.",
  "remediation": "Review the product and plan the necessary updates.",
  "riskType": "end_of_life_product_provisional",
  "riskSubtype": "cpe:/a:php:php"
}

This response includes more information on the risk type, indicates that the risk is unique rather than generic, and provides a recommendation for risk mitigation.

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

Further reading

To learn more about risk management with UpGuard, read these articles next:

Did this answer your question?