Current ThreatQ Version Filter

Working with Indicators

This section demonstrates how to manage indicators in ThreatQ using the SDK, including listing, searching, creating, updating, relating, and bulk-uploading indicators.

List All Indicators

To retrieve all indicators in ThreatQ, use the tq.get() method. This method wraps authentication and performs an HTTP GET request against the ThreatQ API.

The following example calls the /api/indicators endpoint, which returns a collection of indicator objects represented as dictionaries:

inds = tq.get('/api/indicators')
print(inds.get('data')[0])

Example output:

{
  "last_detected_at": null,
  "hash": "51d81f46d7a042805c96e512a3e122ba",
  "status_id": 1,
  "created_at": "2016-10-13 14:07:56",
  "type_id": 10,
  "updated_at": "2016-10-13 14:07:56",
  "value": "1.234.62.166",
  "id": 1,
  "class": "network"
}

Search for a Specific Indicator

To locate a specific indicator, pass search parameters to the tq.get() method using the params argument.

The following example searches for an indicator with the value 8.8.8.8:

ind = tq.get('/api/indicators', params={'value': '8.8.8.8'})
print(ind.get('data'))

Example output:

[
  {
    "last_detected_at": null,
    "hash": "9c709bf480caf30fc107cfbbc107cfbb",
    "status_id": 1,
    "created_at": "2016-10-14 00:02:18",
    "type_id": 10,
    "updated_at": "2016-12-02 09:13:14",
    "value": "8.8.8.8",
    "id": 535253,
    "class": "network"
  }
]

Create a New Indicator

Before creating an indicator, import the required SDK classes:

from threatqsdk import Indicator, Source

Create an indicator by specifying the required fields:

  • value

  • type

  • status

ind = Indicator(tq) ind.set_value('example.com') ind.set_type('FQDN') ind.set_status('Review')

Upload the indicator to ThreatQ and capture the newly assigned indicator ID:

iid = ind.upload(sources=Source('Test'))

Add an Attribute

You can associate custom attributes with an indicator by adding key-value pairs.

Example:

ind.add_attribute('Disposition', 'Safe', sources=Source('Test'))

This adds the attribute Disposition = Safe to the indicator.

Update an Indicator Status

To modify an existing indicator, use the tq.put() method to issue an authenticated HTTP PUT request.

The following example updates an indicator's status from Review to Active using its indicator ID:

tq.put( '/api/indicators/{}'.format(iid), data={'status': 'Active'} )

The variable iid must contain a valid indicator ID.

Retrieve Related Objects

Indicators can be associated with other ThreatQ objects such as indicators, adversaries, events, files, and signatures.

Use the get_related_objects() method to retrieve linked objects. The method accepts an object type as its argument.

Ensure the corresponding object class has been imported before use.

Example:

rel_inds = ind.get_related_objects(Indicator)
rel_advs = ind.get_related_objects(Adversary)

This returns lists of related Indicator and Adversary objects.

The get_related_objects() method is also available for Event, Adversary, File, and Signature objects.

Create Relationships Between Objects

To establish a relationship between two ThreatQ objects, use the relate_object() method.

Example:

ind_a.relate_object(ind_b)

This creates a relationship between the two indicator objects.

The relate_object() method is also available for Event, Adversary, File, and Signature objects.

Bulk Upload Indicators

For large-scale indicator ingestion, use the BulkIndicator class together with the tq.bulkuploadindicators() method.

Import Required Classes

from threatqsdk import BulkIndicator, Source

Create a Collection for Bulk Upload

bulk_indicators = []

Create and Configure Each Bulk Indicator

The following fields are required:

  • ind_value

  • ind_type

  • ind_status

bi = BulkIndicator(tq)
bi.set_value(ind_value)
bi.set_type(ind_type)
bi.set_status(ind_status)

You can also add attributes and relationships:

bi.add_attribute('Foo', 'Bar')
bi.relate_indicator('example.com', 'FQDN')
bi.relate_adversary(adversary_id)
bi.relate_event(event_id)

After configuring the indicator, add it to the bulk upload collection:

bulk_indicators.append(bi)

Repeat this process for each IOC in your dataset.

Upload the Indicators

Once all indicators have been added to the collection, upload them to ThreatQ:

tq.bulkuploadindicators( bulk_indicators, source=Source('Test') )

This submits all indicators in a single bulk operation, improving performance and reducing API overhead when ingesting large volumes of threat intelligence.

 

 

 

 

----------

Indicator Normalization and Validation

Normalization is the process of formatting indicator values into a consistent standard. This prevents duplicate indicators, ensures consistent searching/matching, and improves correlation across data sources.

Common normalization steps include:

  • Converting to lowercase (domains, URLs)
  • Trimming whitespace
  • Removing unnecessary prefixes/suffixes
  • Standardizing formats (e.g., URL structure)

Examples

Raw Input Normalized Value
Example.COM example.com
HTTP://site.com http://site.com

Indicator Validation ensures the indicator is correctly formatted and valid for its type before ingestion. This prevents bad/unusable data from entering ThreatQ, reduces errors in automation/detection systems, and ensures compatibility with downstream tools.

Examples

Type Validation Check
IP Valid IPv4/IPv6 format
Domain Proper domain syntax
Hash Correct length (MD5=32, SHA256=64)
URL Proper scheme (http/https)

Example of Normalization and Validation Workflow

value = " Example.COM "
# Normalize
normalized = value.strip().lower()
# Validate (simple example)
if "." in normalized:
    payload = {
        "value": normalized,
        "type": "domain"
    }
    tq.post("/api/indicators", data=payload)