CLI Quickstart Guide

Prev Next

The Silent Push CLI is a powerful tool that allows you to interact directly with the Silent Push API from your terminal. It supports scoring, enriching, and querying DNS records for indicators of compromise (IOCs), such as domains and IP addresses. This guide covers installation, basic usage, advanced features, scripting, and development extensions.

Installation

To get started, download the Python wheel from the Silent Push Labs repository and install it using pip:

python3 -m pip install SilentPushCLI-0.0.1-py3-none-linux.whl

After installation, set your Silent Push API key as an environment variable:

export SILENT_PUSH_API_KEY=YOUR-API-KEY

Replace YOUR-API-KEY with your actual API key.

Usage

The CLI follows this syntax:

sp COMMAND [SUB-COMMAND...] IOC [PARAMETER=VALUE...] [OPTION...]

Examples

Score a single domain:

sp score ig.com

Enrich a domain with explanations:

sp enrich ig.com -es

Bulk enrich multiple domains:

sp bulk_enrich ig.com x.com ibm.com -es

Query DNS records:

sp padns query a ig.com limit=2 sort=last_seen/-

Supported Commands and Sub-commands

The CLI currently supports the following commands and sub-commands:

Main Commands

These are the top-level commands you can run directly.

Command

Description

score

Calculate risk scores for one or more Indicators of Compromise (IOCs).

enrich

Enrich a single IOC with additional threat intelligence data.

bulk_enrich

Enrich multiple IOCs in a single batch operation (ideal for large lists).

padns

Enter the Passive DNS query context to access PADNS sub-commands (see below).

load

Load a command context (e.g., load padns to switch to PADNS mode).

unload

Unload the current command context and return to the main level.

PADNS Sub-commands

After entering PADNS mode (padns or load padns), use these sub-commands to build precise Passive DNS queries.

Query Types

Specify the DNS record type you want to search for.

Sub-command

Description

query

General DNS query (any available record type).

any

Query any record type.

anyipv4

Query records associated with IPv4 addresses.

anyipv6

Query records associated with IPv6 addresses.

a

Query A records (IPv4 addresses).

aaaa

Query AAAA records (IPv6 addresses).

cname

Query CNAME records (canonical names).

mx

Query MX records (mail exchangers).

ns

Query NS records (name servers).

ptr4

Query PTR records for IPv4 (reverse lookups).

ptr6

Query PTR records for IPv6 (reverse lookups).

soa

Query SOA records (Start of Authority).

txt

Query TXT records (text data, often SPF/DKIM).

Answer Types

Focus on specific answer content returned in DNS records.

Sub-command

Description

answer

Reverse lookup for any answer values.

a

A record answers (IPv4).

aaaa

AAAA record answers (IPv6).

cname

CNAME record answers.

mx

MX record answers.

mxhash

Hashed MX record answers (useful for clustering).

ns

NS record answers.

nshash

Hashed NS record answers.

ptr4

PTR4 record answers.

ptr6

PTR6 record answers.

soa

SOA record answers.

soahash

Hashed SOA record answers.

txt

TXT record answers.

txthash

Hashed TXT record answers.

Quick Tips

  • Use load padns to enter PADNS mode and access all sub-commands without prefixing.

  • Chain sub-commands for precise queries (e.g., padns a answer for A record reverse lookups).

  • Type help or help [command] in the CLI for usage examples and available options.

Options

Options can be applied to most commands to customize the output.

Global options (all commands)

  • -j, --json: Output in JSON format (default).

  • -c, --csv: Output in CSV format.

  • -t, --tsv: Output in TSV format.

  • -h, --help: Display help for the command.

Enrich/Bulk Enrich specific options

  • -e, --explain: Include details on data used for score calculations.

  • -s, --scan_data: Include Host scanning data details.

Interactive Mode

Launch the interactive console by running sp without arguments. This enters the sp console, where you can execute commands without the sp prefix.

Example session

SP# score ig.com
        {
        "domain": "ig.com",
        "sp_risk_score": 18,
        "sp_risk_score_explain": {
        "sp_risk_score_decider": "ns_reputation_score"
        }
        }

        SP# padns query a ig.com limit=1
        {
        "records": [
        {
        "answer": "195.234.39.132",
        "count": 2681,
        "first_seen": "2021-04-17 03:47:18",
        "last_seen": "2024-08-16 12:11:22",
        "query": "ig.com",
        "type": "A"
        }
        ]
        }

        SP#

Load and Unload Commands

Use load to switch to a specific command context, loading its sub-commands for easier access. unload returns to the base console.

Example: Loading PADNS Context

SP# load padns
        PADNS loaded
        SP (PADNS)# query ns ig.com limit=1
        {
        "records": [
        {
        "answer": "dns1.p09.nsone.net",
        "count": 5963,
        "first_seen": "2020-12-26 00:41:26",
        "last_seen": "2024-08-16 09:25:09",
        "nshash": "981275157feda43a53ff6d166de985ff",
        "query": "ig.com",
        "ttl": 172800,
        "type": "NS"
        }
        ]
        }

        SP (PADNS)# answer ns dns1.p09.nsone.net limit=1
        {
        "records": [
        {
        "answer": "dns1.p09.nsone.net",
        "count": 138,
        "first_seen": "2024-01-27 21:23:33",
        "last_seen": "2024-08-16 13:42:25",
        "nshash": "9b484fe18c1a52f56775302e5be302f8",
        "query": "tumblersforyou.com",
        "ttl": 3600,
        "type": "NS"
        }
        ]
        }

        SP (PADNS)# unload padns
        PADNS unloaded
        SP#

You can still run base commands (e.g., score) while in a loaded context.

Scripting

The CLI supports scripting for automation in projects.

run_pyscript Command

Execute a Python script that interacts with the CLI. Example script my_script.py):

# my_script.py
        result = app('score ibm.com -t')
        print(result.data)

Run it with:

sp run_pyscript my_script.py

run_script Command

Run a text file with CLI commands (one per line). Example file my_script.txt):

# my_script.txt
        padns query mx ig.com limit=2
        score ig.com -c

Execute with:

sp run_script my_script.txt

Alternatively, pipe input:

sp < my_script.txt

Batch Execution Tips

Leverage shell scripting for efficient bulk operations. For example, enrich domains from a file:

cat to_enrich.txt | xargs sp bulk_enrich

Note: Keep IOC types consistent in the file (e.g., all domains or all IPs) to avoid errors.

For Developers

Using the Library

Integrate the CLI as a Python library in your code.

Simple Usage

from sp.main import main as sp

        sp(['enrich ig.com'])
        sp(['padns query ns ig.com limit=2'])

Advanced Usage with App Instance

from sp.main import App
        from sp.common.utils import AppFileManager

        app = App(application_manager=AppFileManager('my app'))
        app.onecmd_plus_hooks('enrich ig.com')
        print(app.last_result)
        app.onecmd_plus_hooks('padns query ns ig.com limit=2')
        print(app.last_result)

Extend the Commands – Guidelines

Commands are defined in the sp/commands directory. The project uses the CMD2 library. To add a new command:

  • Create a new Python file in sp/commands/ (e.g., my_new_command.py).

  • Follow this template:

@with_default_category("My New Category")
        class MyNewCommandSet(BaseCommandSet):
        my_new_parser = BaseCommandSet._get_arg_parser()
        my_new_parser.add_argument("-s", "--some_argument")

        @with_argparser(my_new_parser)
        def do_something(self, params: Statement):
        with self.MyNewCommand(params, self) as my_new_command:
        my_new_command.something()

        class MyNewCommand(BaseCommand):

        def __enter__(self):
        # Pre-execution setup
        super().__enter__()
        return self

        def something(self):
        # Core logic
        self._response = {"result": "your command result"}

        def __exit__(self, exc_type, exc_val, exc_tb):
        # Post-execution cleanup
        super().__exit__(exc_type, exc_val, exc_tb)
  • Import it in sp/commands/__init__.py:

# After existing imports
        from .my_new_command import *
  • Add it to initial commands in sp/settings.py:

def get_initial_commands():
        from sp.commands import (
        # Other imports
        MyNewCommandSet
        )
        return {
        # Other commands
        MyNewCommandSet(),
        }

Test your command:

sp your_command --help