id = "shodan"
name = "Shodan"
homepage = "https://www.shodan.io/"
description = "Shodan is a search engine for Internet-connected devices."
executables = ["shodan"]
[dotfiles]
paths = []
secret = ["~/.shodan/api_key", "~/.config/shodan/api_key"]
[commands]
format = 1
label = "Shodan"
description = "Search Shodan, look up a host or domain, and count results. Needs an API key set with shodan init. Download, stream, alerts and scanning are left out."
quality = "ai-draft"
parser = { end_of_options = "--", interleave = "permute", long_equals = true, short_attached = true, short_bundles = false }
[[commands.subcommand]]
path = ["search"]
label = "Search"
description = "Search Shodan and print matching banners."
[[commands.subcommand.source]]
id = "shodan-src"
kind = "manual"
url = "https://github.com/achillean/shodan-python/blob/master/shodan/__main__.py"
revision = "shodan-python master"
evidence = '''@main.command()
@click.option('--fields', help='List of properties to show in the search results.', default='ip_str,port,hostnames,data')
@click.option('--limit', help='The number of search results that should be returned. Maximum: 1000', default=100, type=int)
@click.option('--separator', help='The separator between the properties of the search results.', default='\t')
@click.argument('query', metavar='<search query>', nargs=-1)
def search(color, fields, limit, separator, query):'''
[[commands.subcommand.field]]
id = "query"
label = "Search query"
type = "string"
position = 0
multiple = true
min = 1
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "limit"
label = "Result limit"
type = "integer"
option = ["--limit"]
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "fields"
label = "Fields"
description = "Comma-separated properties."
type = "string"
option = ["--fields"]
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "separator"
label = "Separator"
type = "string"
option = ["--separator"]
sources = ["shodan-src"]
[[commands.subcommand.task]]
id = "search"
label = "Search"
fields = ["query", "limit", "fields"]
required = ["query"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["query", "limit", "fields"]
[[commands.subcommand.group]]
id = "advanced"
label = "Advanced"
fields = ["separator"]
[[commands.subcommand]]
path = ["host"]
label = "Host lookup"
description = "Show everything known about an IP address."
[[commands.subcommand.source]]
id = "shodan-src"
kind = "manual"
url = "https://github.com/achillean/shodan-python/blob/master/shodan/__main__.py"
revision = "shodan-python master"
evidence = '''@main.command()
@click.option('--format', help='The output format for the host information. Possible values are: pretty, tsv.', default='pretty', type=click.Choice(['pretty', 'tsv']))
@click.option('--history', help='Show the complete history of the host.', default=False, is_flag=True)
@click.option('--filename', '-O', help='Save the host information in the given file (append if file exists).', default=None)
@click.argument('ip', metavar='<ip address>')
def host(format, history, filename, save, ip):'''
[[commands.subcommand.field]]
id = "ip"
label = "IP address"
type = "string"
position = 0
min = 1
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "history"
label = "Include history"
type = "boolean"
option = ["--history"]
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "format"
label = "Format"
type = "enum"
option = ["--format"]
choices = [{ value = "pretty", label = "Pretty" }, { value = "tsv", label = "TSV" }]
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "filename"
label = "Save to file"
type = "path"
option = ["--filename", "-O"]
path = { kind = "file", role = "output" }
sources = ["shodan-src"]
[[commands.subcommand.task]]
id = "host"
label = "Look up an IP"
fields = ["ip", "history", "format"]
required = ["ip"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["ip", "history", "format", "filename"]
[[commands.subcommand]]
path = ["count"]
label = "Count results"
description = "Count how many results match a query."
[[commands.subcommand.source]]
id = "shodan-src"
kind = "manual"
url = "https://github.com/achillean/shodan-python/blob/master/shodan/__main__.py"
revision = "shodan-python master"
evidence = '''@main.command()
@click.argument('query', metavar='<search query>', nargs=-1)
def count(query):'''
[[commands.subcommand.field]]
id = "query"
label = "Search query"
type = "string"
position = 0
multiple = true
min = 1
sources = ["shodan-src"]
[[commands.subcommand.task]]
id = "count"
label = "Count"
fields = ["query"]
required = ["query"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["query"]
[[commands.subcommand]]
path = ["domain"]
label = "Domain info"
description = "Show DNS records and subdomains for a domain."
[[commands.subcommand.source]]
id = "shodan-src"
kind = "manual"
url = "https://github.com/achillean/shodan-python/blob/master/shodan/__main__.py"
revision = "shodan-python master"
evidence = '''@main.command(name='domain')
@click.argument('domain', metavar='<domain>')
@click.option('--details', '-D', help='Lookup host information for any IPs in the domain results', default=False, is_flag=True)
@click.option('--history', '-H', help='Include historical DNS data in the results', default=False, is_flag=True)
@click.option('--type', '-T', help='Only returns DNS records of the provided type', default=None)'''
[[commands.subcommand.field]]
id = "domain"
label = "Domain"
type = "string"
position = 0
min = 1
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "details"
label = "Look up host details"
type = "boolean"
option = ["--details", "-D"]
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "history"
label = "Historical DNS data"
type = "boolean"
option = ["--history", "-H"]
sources = ["shodan-src"]
[[commands.subcommand.field]]
id = "type"
label = "Record type"
type = "string"
option = ["--type", "-T"]
suggestions = [{ value = "A", label = "A" }, { value = "MX", label = "MX" }, { value = "TXT", label = "TXT" }]
sources = ["shodan-src"]
[[commands.subcommand.task]]
id = "domain"
label = "Look up a domain"
fields = ["domain", "type"]
required = ["domain"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["domain", "details", "history", "type"]