Full Code of smicallef/spiderfoot for AI

master 0f815a203afe cached
795 files
13.2 MB
3.5M tokens
4203 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (13,940K chars total). Download the full file to get everything.
Repository: smicallef/spiderfoot
Branch: master
Commit: 0f815a203afe
Files: 795
Total size: 13.2 MB

Directory structure:
gitextract_l429po4y/

├── .dockerignore
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       ├── codeql-analysis.yml
│       └── tests.yaml
├── .gitignore
├── .pylintrc
├── Dockerfile
├── Dockerfile.full
├── LICENSE
├── README.md
├── THANKYOU
├── VERSION
├── correlations/
│   ├── README.md
│   ├── cert_expired.yaml
│   ├── cloud_bucket_open.yaml
│   ├── cloud_bucket_open_related.yaml
│   ├── data_from_base64.yaml
│   ├── data_from_docmeta.yaml
│   ├── database_exposed.yaml
│   ├── dev_or_test_system.yaml
│   ├── dns_zone_transfer_possible.yaml
│   ├── egress_ip_from_wikipedia.yaml
│   ├── email_in_multiple_breaches.yaml
│   ├── email_in_whois.yaml
│   ├── email_only_from_pasteleak_site.yaml
│   ├── host_only_from_bruteforce.yaml
│   ├── host_only_from_certificatetransparency.yaml
│   ├── http_errors.yaml
│   ├── human_name_in_whois.yaml
│   ├── internal_host.yaml
│   ├── multiple_malicious.yaml
│   ├── multiple_malicious_affiliate.yaml
│   ├── multiple_malicious_cohost.yaml
│   ├── name_only_from_pasteleak_site.yaml
│   ├── open_port_version.yaml
│   ├── outlier_cloud.yaml
│   ├── outlier_country.yaml
│   ├── outlier_email.yaml
│   ├── outlier_hostname.yaml
│   ├── outlier_ipaddress.yaml
│   ├── outlier_registrar.yaml
│   ├── outlier_webserver.yaml
│   ├── remote_desktop_exposed.yaml
│   ├── root_path_needs_auth.yaml
│   ├── stale_host.yaml
│   ├── strong_affiliate_certs.yaml
│   ├── strong_similardomain_crossref.yaml
│   ├── template.yaml
│   ├── vulnerability_critical.yaml
│   ├── vulnerability_high.yaml
│   └── vulnerability_mediumlow.yaml
├── docker-compose-dev.yml
├── docker-compose-full.yml
├── docker-compose.yml
├── docs/
│   ├── Makefile
│   ├── conf.py
│   ├── index.rst
│   ├── make.bat
│   └── spiderfoot.rst
├── generate-certificate
├── modules/
│   ├── __init__.py
│   ├── sfp__stor_db.py
│   ├── sfp__stor_stdout.py
│   ├── sfp_abstractapi.py
│   ├── sfp_abusech.py
│   ├── sfp_abuseipdb.py
│   ├── sfp_abusix.py
│   ├── sfp_accounts.py
│   ├── sfp_adblock.py
│   ├── sfp_adguard_dns.py
│   ├── sfp_ahmia.py
│   ├── sfp_alienvault.py
│   ├── sfp_alienvaultiprep.py
│   ├── sfp_apple_itunes.py
│   ├── sfp_archiveorg.py
│   ├── sfp_arin.py
│   ├── sfp_azureblobstorage.py
│   ├── sfp_base64.py
│   ├── sfp_bgpview.py
│   ├── sfp_binaryedge.py
│   ├── sfp_bingsearch.py
│   ├── sfp_bingsharedip.py
│   ├── sfp_binstring.py
│   ├── sfp_bitcoin.py
│   ├── sfp_bitcoinabuse.py
│   ├── sfp_bitcoinwhoswho.py
│   ├── sfp_blockchain.py
│   ├── sfp_blocklistde.py
│   ├── sfp_botscout.py
│   ├── sfp_botvrij.py
│   ├── sfp_builtwith.py
│   ├── sfp_c99.py
│   ├── sfp_callername.py
│   ├── sfp_censys.py
│   ├── sfp_certspotter.py
│   ├── sfp_cinsscore.py
│   ├── sfp_circllu.py
│   ├── sfp_citadel.py
│   ├── sfp_cleanbrowsing.py
│   ├── sfp_cleantalk.py
│   ├── sfp_clearbit.py
│   ├── sfp_cloudflaredns.py
│   ├── sfp_coinblocker.py
│   ├── sfp_commoncrawl.py
│   ├── sfp_comodo.py
│   ├── sfp_company.py
│   ├── sfp_cookie.py
│   ├── sfp_countryname.py
│   ├── sfp_creditcard.py
│   ├── sfp_crobat_api.py
│   ├── sfp_crossref.py
│   ├── sfp_crt.py
│   ├── sfp_crxcavator.py
│   ├── sfp_customfeed.py
│   ├── sfp_cybercrimetracker.py
│   ├── sfp_debounce.py
│   ├── sfp_dehashed.py
│   ├── sfp_digitaloceanspace.py
│   ├── sfp_dns_for_family.py
│   ├── sfp_dnsbrute.py
│   ├── sfp_dnscommonsrv.py
│   ├── sfp_dnsdb.py
│   ├── sfp_dnsdumpster.py
│   ├── sfp_dnsgrep.py
│   ├── sfp_dnsneighbor.py
│   ├── sfp_dnsraw.py
│   ├── sfp_dnsresolve.py
│   ├── sfp_dnszonexfer.py
│   ├── sfp_dronebl.py
│   ├── sfp_duckduckgo.py
│   ├── sfp_email.py
│   ├── sfp_emailcrawlr.py
│   ├── sfp_emailformat.py
│   ├── sfp_emailrep.py
│   ├── sfp_emergingthreats.py
│   ├── sfp_errors.py
│   ├── sfp_ethereum.py
│   ├── sfp_etherscan.py
│   ├── sfp_filemeta.py
│   ├── sfp_flickr.py
│   ├── sfp_focsec.py
│   ├── sfp_fortinet.py
│   ├── sfp_fraudguard.py
│   ├── sfp_fsecure_riddler.py
│   ├── sfp_fullcontact.py
│   ├── sfp_fullhunt.py
│   ├── sfp_github.py
│   ├── sfp_gleif.py
│   ├── sfp_google_tag_manager.py
│   ├── sfp_googlemaps.py
│   ├── sfp_googleobjectstorage.py
│   ├── sfp_googlesafebrowsing.py
│   ├── sfp_googlesearch.py
│   ├── sfp_gravatar.py
│   ├── sfp_grayhatwarfare.py
│   ├── sfp_greensnow.py
│   ├── sfp_grep_app.py
│   ├── sfp_greynoise.py
│   ├── sfp_greynoise_community.py
│   ├── sfp_h1nobbdde.py
│   ├── sfp_hackertarget.py
│   ├── sfp_hashes.py
│   ├── sfp_haveibeenpwned.py
│   ├── sfp_honeypot.py
│   ├── sfp_hosting.py
│   ├── sfp_hostio.py
│   ├── sfp_hunter.py
│   ├── sfp_hybrid_analysis.py
│   ├── sfp_iban.py
│   ├── sfp_iknowwhatyoudownload.py
│   ├── sfp_intelx.py
│   ├── sfp_intfiles.py
│   ├── sfp_ipapico.py
│   ├── sfp_ipapicom.py
│   ├── sfp_ipinfo.py
│   ├── sfp_ipqualityscore.py
│   ├── sfp_ipregistry.py
│   ├── sfp_ipstack.py
│   ├── sfp_isc.py
│   ├── sfp_jsonwhoiscom.py
│   ├── sfp_junkfiles.py
│   ├── sfp_keybase.py
│   ├── sfp_koodous.py
│   ├── sfp_leakix.py
│   ├── sfp_maltiverse.py
│   ├── sfp_malwarepatrol.py
│   ├── sfp_metadefender.py
│   ├── sfp_mnemonic.py
│   ├── sfp_multiproxy.py
│   ├── sfp_myspace.py
│   ├── sfp_nameapi.py
│   ├── sfp_names.py
│   ├── sfp_networksdb.py
│   ├── sfp_neutrinoapi.py
│   ├── sfp_numverify.py
│   ├── sfp_onioncity.py
│   ├── sfp_onionsearchengine.py
│   ├── sfp_onyphe.py
│   ├── sfp_openbugbounty.py
│   ├── sfp_opencorporates.py
│   ├── sfp_opendns.py
│   ├── sfp_opennic.py
│   ├── sfp_openphish.py
│   ├── sfp_openstreetmap.py
│   ├── sfp_pageinfo.py
│   ├── sfp_pastebin.py
│   ├── sfp_pgp.py
│   ├── sfp_phishstats.py
│   ├── sfp_phishtank.py
│   ├── sfp_phone.py
│   ├── sfp_portscan_tcp.py
│   ├── sfp_projectdiscovery.py
│   ├── sfp_psbdmp.py
│   ├── sfp_pulsedive.py
│   ├── sfp_punkspider.py
│   ├── sfp_quad9.py
│   ├── sfp_reversewhois.py
│   ├── sfp_ripe.py
│   ├── sfp_riskiq.py
│   ├── sfp_robtex.py
│   ├── sfp_s3bucket.py
│   ├── sfp_searchcode.py
│   ├── sfp_securitytrails.py
│   ├── sfp_seon.py
│   ├── sfp_shodan.py
│   ├── sfp_similar.py
│   ├── sfp_skymem.py
│   ├── sfp_slideshare.py
│   ├── sfp_snov.py
│   ├── sfp_social.py
│   ├── sfp_sociallinks.py
│   ├── sfp_socialprofiles.py
│   ├── sfp_sorbs.py
│   ├── sfp_spamcop.py
│   ├── sfp_spamhaus.py
│   ├── sfp_spider.py
│   ├── sfp_spur.py
│   ├── sfp_spyonweb.py
│   ├── sfp_sslcert.py
│   ├── sfp_stackoverflow.py
│   ├── sfp_stevenblack_hosts.py
│   ├── sfp_strangeheaders.py
│   ├── sfp_subdomain_takeover.py
│   ├── sfp_sublist3r.py
│   ├── sfp_surbl.py
│   ├── sfp_talosintel.py
│   ├── sfp_template.py
│   ├── sfp_textmagic.py
│   ├── sfp_threatcrowd.py
│   ├── sfp_threatfox.py
│   ├── sfp_threatjammer.py
│   ├── sfp_threatminer.py
│   ├── sfp_tldsearch.py
│   ├── sfp_tool_cmseek.py
│   ├── sfp_tool_dnstwist.py
│   ├── sfp_tool_nbtscan.py
│   ├── sfp_tool_nmap.py
│   ├── sfp_tool_nuclei.py
│   ├── sfp_tool_onesixtyone.py
│   ├── sfp_tool_retirejs.py
│   ├── sfp_tool_snallygaster.py
│   ├── sfp_tool_testsslsh.py
│   ├── sfp_tool_trufflehog.py
│   ├── sfp_tool_wafw00f.py
│   ├── sfp_tool_wappalyzer.py
│   ├── sfp_tool_whatweb.py
│   ├── sfp_torch.py
│   ├── sfp_torexits.py
│   ├── sfp_trashpanda.py
│   ├── sfp_trumail.py
│   ├── sfp_twilio.py
│   ├── sfp_twitter.py
│   ├── sfp_uceprotect.py
│   ├── sfp_urlscan.py
│   ├── sfp_venmo.py
│   ├── sfp_viewdns.py
│   ├── sfp_virustotal.py
│   ├── sfp_voipbl.py
│   ├── sfp_vxvault.py
│   ├── sfp_webanalytics.py
│   ├── sfp_webframework.py
│   ├── sfp_webserver.py
│   ├── sfp_whatcms.py
│   ├── sfp_whois.py
│   ├── sfp_whoisology.py
│   ├── sfp_whoxy.py
│   ├── sfp_wigle.py
│   ├── sfp_wikileaks.py
│   ├── sfp_wikipediaedits.py
│   ├── sfp_xforce.py
│   ├── sfp_yandexdns.py
│   ├── sfp_zetalytics.py
│   ├── sfp_zonefiles.py
│   └── sfp_zoneh.py
├── requirements.txt
├── setup.cfg
├── sf.py
├── sfcli.py
├── sflib.py
├── sfscan.py
├── sfwebui.py
├── spiderfoot/
│   ├── __init__.py
│   ├── __version__.py
│   ├── correlation.py
│   ├── db.py
│   ├── dicts/
│   │   ├── __init__.py
│   │   ├── generic-usernames.txt
│   │   ├── ispell/
│   │   │   ├── LICENSE
│   │   │   ├── __init__.py
│   │   │   ├── english.dict
│   │   │   ├── french.dict
│   │   │   ├── german.dict
│   │   │   ├── names.dict
│   │   │   └── spanish.dict
│   │   ├── subdomains-10000.txt
│   │   └── subdomains.txt
│   ├── event.py
│   ├── helpers.py
│   ├── logger.py
│   ├── plugin.py
│   ├── static/
│   │   ├── css/
│   │   │   ├── dark.css
│   │   │   └── spiderfoot.css
│   │   ├── js/
│   │   │   ├── spiderfoot.js
│   │   │   ├── spiderfoot.newscan.js
│   │   │   ├── spiderfoot.opts.js
│   │   │   ├── spiderfoot.scanlist.js
│   │   │   └── viz.js
│   │   └── package.json
│   ├── target.py
│   ├── templates/
│   │   ├── FOOTER.tmpl
│   │   ├── HEADER.tmpl
│   │   ├── error.tmpl
│   │   ├── newscan.tmpl
│   │   ├── opts.tmpl
│   │   ├── scaninfo.tmpl
│   │   └── scanlist.tmpl
│   └── threadpool.py
└── test/
    ├── README.md
    ├── __init__.py
    ├── acceptance/
    │   ├── requirements.txt
    │   ├── run
    │   └── scan.robot
    ├── bandit
    ├── conftest.py
    ├── integration/
    │   ├── __init__.py
    │   ├── modules/
    │   │   ├── __init__.py
    │   │   ├── test_sfp__stor_db.py
    │   │   ├── test_sfp__stor_stdout.py
    │   │   ├── test_sfp_abstractapi.py
    │   │   ├── test_sfp_abusech.py
    │   │   ├── test_sfp_abuseipdb.py
    │   │   ├── test_sfp_abusix.py
    │   │   ├── test_sfp_accounts.py
    │   │   ├── test_sfp_adblock.py
    │   │   ├── test_sfp_adguard_dns.py
    │   │   ├── test_sfp_ahmia.py
    │   │   ├── test_sfp_alienvault.py
    │   │   ├── test_sfp_alienvaultiprep.py
    │   │   ├── test_sfp_apple_itunes.py
    │   │   ├── test_sfp_archiveorg.py
    │   │   ├── test_sfp_arin.py
    │   │   ├── test_sfp_azureblobstorage.py
    │   │   ├── test_sfp_bgpview.py
    │   │   ├── test_sfp_binaryedge.py
    │   │   ├── test_sfp_bingsearch.py
    │   │   ├── test_sfp_bingsharedip.py
    │   │   ├── test_sfp_bitcoinabuse.py
    │   │   ├── test_sfp_bitcoinwhoswho.py
    │   │   ├── test_sfp_blockchain.py
    │   │   ├── test_sfp_blocklistde.py
    │   │   ├── test_sfp_botscout.py
    │   │   ├── test_sfp_botvrij.py
    │   │   ├── test_sfp_builtwith.py
    │   │   ├── test_sfp_c99.py
    │   │   ├── test_sfp_callername.py
    │   │   ├── test_sfp_censys.py
    │   │   ├── test_sfp_certspotter.py
    │   │   ├── test_sfp_cinsscore.py
    │   │   ├── test_sfp_circllu.py
    │   │   ├── test_sfp_citadel.py
    │   │   ├── test_sfp_cleanbrowsing.py
    │   │   ├── test_sfp_cleantalk.py
    │   │   ├── test_sfp_clearbit.py
    │   │   ├── test_sfp_cloudflaredns.py
    │   │   ├── test_sfp_coinblocker.py
    │   │   ├── test_sfp_commoncrawl.py
    │   │   ├── test_sfp_comodo.py
    │   │   ├── test_sfp_crobat_api.py
    │   │   ├── test_sfp_crossref.py
    │   │   ├── test_sfp_crt.py
    │   │   ├── test_sfp_crxcavator.py
    │   │   ├── test_sfp_customfeed.py
    │   │   ├── test_sfp_cybercrimetracker.py
    │   │   ├── test_sfp_debounce.py
    │   │   ├── test_sfp_dehashed.py
    │   │   ├── test_sfp_digitaloceanspace.py
    │   │   ├── test_sfp_dns_for_family.py
    │   │   ├── test_sfp_dnsbrute.py
    │   │   ├── test_sfp_dnscommonsrv.py
    │   │   ├── test_sfp_dnsdb.py
    │   │   ├── test_sfp_dnsdumpster.py
    │   │   ├── test_sfp_dnsgrep.py
    │   │   ├── test_sfp_dnsneighbor.py
    │   │   ├── test_sfp_dnsraw.py
    │   │   ├── test_sfp_dnsresolve.py
    │   │   ├── test_sfp_dnszonexfer.py
    │   │   ├── test_sfp_dronebl.py
    │   │   ├── test_sfp_duckduckgo.py
    │   │   ├── test_sfp_email.py
    │   │   ├── test_sfp_emailcrawlr.py
    │   │   ├── test_sfp_emailformat.py
    │   │   ├── test_sfp_emailrep.py
    │   │   ├── test_sfp_emergingthreats.py
    │   │   ├── test_sfp_etherscan.py
    │   │   ├── test_sfp_filemeta.py
    │   │   ├── test_sfp_flickr.py
    │   │   ├── test_sfp_focsec.py
    │   │   ├── test_sfp_fortinet.py
    │   │   ├── test_sfp_fraudguard.py
    │   │   ├── test_sfp_fsecure_riddler.py
    │   │   ├── test_sfp_fullcontact.py
    │   │   ├── test_sfp_fullhunt.py
    │   │   ├── test_sfp_github.py
    │   │   ├── test_sfp_gleif.py
    │   │   ├── test_sfp_google_tag_manager.py
    │   │   ├── test_sfp_googlemaps.py
    │   │   ├── test_sfp_googleobjectstorage.py
    │   │   ├── test_sfp_googlesafebrowsing.py
    │   │   ├── test_sfp_googlesearch.py
    │   │   ├── test_sfp_gravatar.py
    │   │   ├── test_sfp_grayhatwarfare.py
    │   │   ├── test_sfp_greensnow.py
    │   │   ├── test_sfp_grep_app.py
    │   │   ├── test_sfp_greynoise.py
    │   │   ├── test_sfp_h1nobbdde.py
    │   │   ├── test_sfp_hackertarget.py
    │   │   ├── test_sfp_haveibeenpwned.py
    │   │   ├── test_sfp_honeypot.py
    │   │   ├── test_sfp_hosting.py
    │   │   ├── test_sfp_hostio.py
    │   │   ├── test_sfp_hunter.py
    │   │   ├── test_sfp_hybrid_analysis.py
    │   │   ├── test_sfp_iknowwhatyoudownload.py
    │   │   ├── test_sfp_intelx.py
    │   │   ├── test_sfp_ipapico.py
    │   │   ├── test_sfp_ipapicom.py
    │   │   ├── test_sfp_ipinfo.py
    │   │   ├── test_sfp_ipqualityscore.py
    │   │   ├── test_sfp_ipregistry.py
    │   │   ├── test_sfp_ipstack.py
    │   │   ├── test_sfp_isc.py
    │   │   ├── test_sfp_jsonwhoiscom.py
    │   │   ├── test_sfp_junkfiles.py
    │   │   ├── test_sfp_keybase.py
    │   │   ├── test_sfp_koodous.py
    │   │   ├── test_sfp_leakix.py
    │   │   ├── test_sfp_maltiverse.py
    │   │   ├── test_sfp_malwarepatrol.py
    │   │   ├── test_sfp_metadefender.py
    │   │   ├── test_sfp_mnemonic.py
    │   │   ├── test_sfp_multiproxy.py
    │   │   ├── test_sfp_myspace.py
    │   │   ├── test_sfp_nameapi.py
    │   │   ├── test_sfp_networksdb.py
    │   │   ├── test_sfp_neutrinoapi.py
    │   │   ├── test_sfp_numverify.py
    │   │   ├── test_sfp_onioncity.py
    │   │   ├── test_sfp_onionsearchengine.py
    │   │   ├── test_sfp_onyphe.py
    │   │   ├── test_sfp_openbugbounty.py
    │   │   ├── test_sfp_opencorporates.py
    │   │   ├── test_sfp_opendns.py
    │   │   ├── test_sfp_opennic.py
    │   │   ├── test_sfp_openphish.py
    │   │   ├── test_sfp_openstreetmap.py
    │   │   ├── test_sfp_pageinfo.py
    │   │   ├── test_sfp_pastebin.py
    │   │   ├── test_sfp_pgp.py
    │   │   ├── test_sfp_phishstats.py
    │   │   ├── test_sfp_phishtank.py
    │   │   ├── test_sfp_portscan_tcp.py
    │   │   ├── test_sfp_projectdiscovery.py
    │   │   ├── test_sfp_psbdmp.py
    │   │   ├── test_sfp_pulsedive.py
    │   │   ├── test_sfp_punkspider.py
    │   │   ├── test_sfp_quad9.py
    │   │   ├── test_sfp_reversewhois.py
    │   │   ├── test_sfp_ripe.py
    │   │   ├── test_sfp_riskiq.py
    │   │   ├── test_sfp_robtex.py
    │   │   ├── test_sfp_s3bucket.py
    │   │   ├── test_sfp_searchcode.py
    │   │   ├── test_sfp_securitytrails.py
    │   │   ├── test_sfp_seon.py
    │   │   ├── test_sfp_shodan.py
    │   │   ├── test_sfp_similar.py
    │   │   ├── test_sfp_skymem.py
    │   │   ├── test_sfp_slideshare.py
    │   │   ├── test_sfp_snov.py
    │   │   ├── test_sfp_sociallinks.py
    │   │   ├── test_sfp_socialprofiles.py
    │   │   ├── test_sfp_sorbs.py
    │   │   ├── test_sfp_spamcop.py
    │   │   ├── test_sfp_spamhaus.py
    │   │   ├── test_sfp_spider.py
    │   │   ├── test_sfp_spur.py
    │   │   ├── test_sfp_spyonweb.py
    │   │   ├── test_sfp_sslcert.py
    │   │   ├── test_sfp_stackoverflow.py
    │   │   ├── test_sfp_stevenblack_hosts.py
    │   │   ├── test_sfp_subdomain_takeover.py
    │   │   ├── test_sfp_sublist3r.py
    │   │   ├── test_sfp_surbl.py
    │   │   ├── test_sfp_talosintel.py
    │   │   ├── test_sfp_textmagic.py
    │   │   ├── test_sfp_threatcrowd.py
    │   │   ├── test_sfp_threatfox.py
    │   │   ├── test_sfp_threatminer.py
    │   │   ├── test_sfp_tldsearch.py
    │   │   ├── test_sfp_torch.py
    │   │   ├── test_sfp_torexits.py
    │   │   ├── test_sfp_trashpanda.py
    │   │   ├── test_sfp_trumail.py
    │   │   ├── test_sfp_twilio.py
    │   │   ├── test_sfp_twitter.py
    │   │   ├── test_sfp_uceprotect.py
    │   │   ├── test_sfp_urlscan.py
    │   │   ├── test_sfp_venmo.py
    │   │   ├── test_sfp_viewdns.py
    │   │   ├── test_sfp_virustotal.py
    │   │   ├── test_sfp_voipbl.py
    │   │   ├── test_sfp_vxvault.py
    │   │   ├── test_sfp_webserver.py
    │   │   ├── test_sfp_whatcms.py
    │   │   ├── test_sfp_whois.py
    │   │   ├── test_sfp_whoisology.py
    │   │   ├── test_sfp_whoxy.py
    │   │   ├── test_sfp_wigle.py
    │   │   ├── test_sfp_wikileaks.py
    │   │   ├── test_sfp_wikipediaedits.py
    │   │   ├── test_sfp_xforce.py
    │   │   ├── test_sfp_yandexdns.py
    │   │   ├── test_sfp_zetalytics.py
    │   │   └── test_sfp_zoneh.py
    │   ├── test_sf.py
    │   ├── test_sfcli.py
    │   └── test_sfwebui.py
    ├── requirements.txt
    ├── run
    ├── unit/
    │   ├── __init__.py
    │   ├── modules/
    │   │   ├── __init__.py
    │   │   ├── test_sfp__stor_db.py
    │   │   ├── test_sfp__stor_stdout.py
    │   │   ├── test_sfp_abstractapi.py
    │   │   ├── test_sfp_abusech.py
    │   │   ├── test_sfp_abuseipdb.py
    │   │   ├── test_sfp_abusix.py
    │   │   ├── test_sfp_accounts.py
    │   │   ├── test_sfp_adblock.py
    │   │   ├── test_sfp_adguard_dns.py
    │   │   ├── test_sfp_ahmia.py
    │   │   ├── test_sfp_alienvault.py
    │   │   ├── test_sfp_alienvaultiprep.py
    │   │   ├── test_sfp_apple_itunes.py
    │   │   ├── test_sfp_archiveorg.py
    │   │   ├── test_sfp_arin.py
    │   │   ├── test_sfp_azureblobstorage.py
    │   │   ├── test_sfp_base64.py
    │   │   ├── test_sfp_bgpview.py
    │   │   ├── test_sfp_binaryedge.py
    │   │   ├── test_sfp_bingsearch.py
    │   │   ├── test_sfp_bingsharedip.py
    │   │   ├── test_sfp_binstring.py
    │   │   ├── test_sfp_bitcoin.py
    │   │   ├── test_sfp_bitcoinabuse.py
    │   │   ├── test_sfp_bitcoinwhoswho.py
    │   │   ├── test_sfp_blockchain.py
    │   │   ├── test_sfp_blocklistde.py
    │   │   ├── test_sfp_botscout.py
    │   │   ├── test_sfp_botvrij.py
    │   │   ├── test_sfp_builtwith.py
    │   │   ├── test_sfp_c99.py
    │   │   ├── test_sfp_callername.py
    │   │   ├── test_sfp_censys.py
    │   │   ├── test_sfp_certspotter.py
    │   │   ├── test_sfp_cinsscore.py
    │   │   ├── test_sfp_circllu.py
    │   │   ├── test_sfp_citadel.py
    │   │   ├── test_sfp_cleanbrowsing.py
    │   │   ├── test_sfp_cleantalk.py
    │   │   ├── test_sfp_clearbit.py
    │   │   ├── test_sfp_cloudflaredns.py
    │   │   ├── test_sfp_coinblocker.py
    │   │   ├── test_sfp_commoncrawl.py
    │   │   ├── test_sfp_comodo.py
    │   │   ├── test_sfp_company.py
    │   │   ├── test_sfp_cookie.py
    │   │   ├── test_sfp_countryname.py
    │   │   ├── test_sfp_creditcard.py
    │   │   ├── test_sfp_crobat_api.py
    │   │   ├── test_sfp_crossref.py
    │   │   ├── test_sfp_crt.py
    │   │   ├── test_sfp_crxcavator.py
    │   │   ├── test_sfp_customfeed.py
    │   │   ├── test_sfp_cybercrimetracker.py
    │   │   ├── test_sfp_debounce.py
    │   │   ├── test_sfp_dehashed.py
    │   │   ├── test_sfp_digitaloceanspace.py
    │   │   ├── test_sfp_dns_for_family.py
    │   │   ├── test_sfp_dnsbrute.py
    │   │   ├── test_sfp_dnscommonsrv.py
    │   │   ├── test_sfp_dnsdb.py
    │   │   ├── test_sfp_dnsdumpster.py
    │   │   ├── test_sfp_dnsgrep.py
    │   │   ├── test_sfp_dnsneighbor.py
    │   │   ├── test_sfp_dnsraw.py
    │   │   ├── test_sfp_dnsresolve.py
    │   │   ├── test_sfp_dnszonexfer.py
    │   │   ├── test_sfp_dronebl.py
    │   │   ├── test_sfp_duckduckgo.py
    │   │   ├── test_sfp_email.py
    │   │   ├── test_sfp_emailcrawlr.py
    │   │   ├── test_sfp_emailformat.py
    │   │   ├── test_sfp_emailrep.py
    │   │   ├── test_sfp_emergingthreats.py
    │   │   ├── test_sfp_errors.py
    │   │   ├── test_sfp_ethereum.py
    │   │   ├── test_sfp_etherscan.py
    │   │   ├── test_sfp_filemeta.py
    │   │   ├── test_sfp_flickr.py
    │   │   ├── test_sfp_focsec.py
    │   │   ├── test_sfp_fortinet.py
    │   │   ├── test_sfp_fraudguard.py
    │   │   ├── test_sfp_fsecure_riddler.py
    │   │   ├── test_sfp_fullcontact.py
    │   │   ├── test_sfp_fullhunt.py
    │   │   ├── test_sfp_github.py
    │   │   ├── test_sfp_gleif.py
    │   │   ├── test_sfp_google_tag_manager.py
    │   │   ├── test_sfp_googlemaps.py
    │   │   ├── test_sfp_googleobjectstorage.py
    │   │   ├── test_sfp_googlesafebrowsing.py
    │   │   ├── test_sfp_googlesearch.py
    │   │   ├── test_sfp_gravatar.py
    │   │   ├── test_sfp_grayhatwarfare.py
    │   │   ├── test_sfp_greensnow.py
    │   │   ├── test_sfp_grep_app.py
    │   │   ├── test_sfp_greynoise.py
    │   │   ├── test_sfp_h1nobbdde.py
    │   │   ├── test_sfp_hackertarget.py
    │   │   ├── test_sfp_hashes.py
    │   │   ├── test_sfp_haveibeenpwned.py
    │   │   ├── test_sfp_honeypot.py
    │   │   ├── test_sfp_hosting.py
    │   │   ├── test_sfp_hostio.py
    │   │   ├── test_sfp_hunter.py
    │   │   ├── test_sfp_hybrid_analysis.py
    │   │   ├── test_sfp_iban.py
    │   │   ├── test_sfp_iknowwhatyoudownload.py
    │   │   ├── test_sfp_intelx.py
    │   │   ├── test_sfp_intfiles.py
    │   │   ├── test_sfp_ipapico.py
    │   │   ├── test_sfp_ipapicom.py
    │   │   ├── test_sfp_ipinfo.py
    │   │   ├── test_sfp_ipqualityscore.py
    │   │   ├── test_sfp_ipregistry.py
    │   │   ├── test_sfp_ipstack.py
    │   │   ├── test_sfp_isc.py
    │   │   ├── test_sfp_jsonwhoiscom.py
    │   │   ├── test_sfp_junkfiles.py
    │   │   ├── test_sfp_keybase.py
    │   │   ├── test_sfp_koodous.py
    │   │   ├── test_sfp_leakix.py
    │   │   ├── test_sfp_maltiverse.py
    │   │   ├── test_sfp_malwarepatrol.py
    │   │   ├── test_sfp_metadefender.py
    │   │   ├── test_sfp_mnemonic.py
    │   │   ├── test_sfp_multiproxy.py
    │   │   ├── test_sfp_myspace.py
    │   │   ├── test_sfp_nameapi.py
    │   │   ├── test_sfp_names.py
    │   │   ├── test_sfp_networksdb.py
    │   │   ├── test_sfp_neutrinoapi.py
    │   │   ├── test_sfp_numverify.py
    │   │   ├── test_sfp_onioncity.py
    │   │   ├── test_sfp_onionsearchengine.py
    │   │   ├── test_sfp_onyphe.py
    │   │   ├── test_sfp_openbugbounty.py
    │   │   ├── test_sfp_opencorporates.py
    │   │   ├── test_sfp_opendns.py
    │   │   ├── test_sfp_opennic.py
    │   │   ├── test_sfp_openphish.py
    │   │   ├── test_sfp_openstreetmap.py
    │   │   ├── test_sfp_pageinfo.py
    │   │   ├── test_sfp_pastebin.py
    │   │   ├── test_sfp_pgp.py
    │   │   ├── test_sfp_phishstats.py
    │   │   ├── test_sfp_phishtank.py
    │   │   ├── test_sfp_phone.py
    │   │   ├── test_sfp_portscan_tcp.py
    │   │   ├── test_sfp_projectdiscovery.py
    │   │   ├── test_sfp_psbdmp.py
    │   │   ├── test_sfp_pulsedive.py
    │   │   ├── test_sfp_punkspider.py
    │   │   ├── test_sfp_quad9.py
    │   │   ├── test_sfp_reversewhois.py
    │   │   ├── test_sfp_ripe.py
    │   │   ├── test_sfp_riskiq.py
    │   │   ├── test_sfp_robtex.py
    │   │   ├── test_sfp_s3bucket.py
    │   │   ├── test_sfp_searchcode.py
    │   │   ├── test_sfp_securitytrails.py
    │   │   ├── test_sfp_seon.py
    │   │   ├── test_sfp_shodan.py
    │   │   ├── test_sfp_similar.py
    │   │   ├── test_sfp_skymem.py
    │   │   ├── test_sfp_slideshare.py
    │   │   ├── test_sfp_snov.py
    │   │   ├── test_sfp_social.py
    │   │   ├── test_sfp_sociallinks.py
    │   │   ├── test_sfp_socialprofiles.py
    │   │   ├── test_sfp_sorbs.py
    │   │   ├── test_sfp_spamcop.py
    │   │   ├── test_sfp_spamhaus.py
    │   │   ├── test_sfp_spider.py
    │   │   ├── test_sfp_spur.py
    │   │   ├── test_sfp_spyonweb.py
    │   │   ├── test_sfp_sslcert.py
    │   │   ├── test_sfp_stackoverflow.py
    │   │   ├── test_sfp_stevenblack_hosts.py
    │   │   ├── test_sfp_strangeheaders.py
    │   │   ├── test_sfp_subdomain_takeover.py
    │   │   ├── test_sfp_sublist3r.py
    │   │   ├── test_sfp_surbl.py
    │   │   ├── test_sfp_talosintel.py
    │   │   ├── test_sfp_template.py
    │   │   ├── test_sfp_textmagic.py
    │   │   ├── test_sfp_threatcrowd.py
    │   │   ├── test_sfp_threatfox.py
    │   │   ├── test_sfp_threatminer.py
    │   │   ├── test_sfp_tldsearch.py
    │   │   ├── test_sfp_tool_cmseek.py
    │   │   ├── test_sfp_tool_dnstwist.py
    │   │   ├── test_sfp_tool_nbtscan.py
    │   │   ├── test_sfp_tool_nmap.py
    │   │   ├── test_sfp_tool_nuclei.py
    │   │   ├── test_sfp_tool_onesixtyone.py
    │   │   ├── test_sfp_tool_retirejs.py
    │   │   ├── test_sfp_tool_snallygaster.py
    │   │   ├── test_sfp_tool_testsslsh.py
    │   │   ├── test_sfp_tool_trufflehog.py
    │   │   ├── test_sfp_tool_wafw00f.py
    │   │   ├── test_sfp_tool_wappalyzer.py
    │   │   ├── test_sfp_tool_whatweb.py
    │   │   ├── test_sfp_torch.py
    │   │   ├── test_sfp_torexits.py
    │   │   ├── test_sfp_trashpanda.py
    │   │   ├── test_sfp_trumail.py
    │   │   ├── test_sfp_twilio.py
    │   │   ├── test_sfp_twitter.py
    │   │   ├── test_sfp_uceprotect.py
    │   │   ├── test_sfp_urlscan.py
    │   │   ├── test_sfp_venmo.py
    │   │   ├── test_sfp_viewdns.py
    │   │   ├── test_sfp_virustotal.py
    │   │   ├── test_sfp_voipbl.py
    │   │   ├── test_sfp_vxvault.py
    │   │   ├── test_sfp_webanalytics.py
    │   │   ├── test_sfp_webframework.py
    │   │   ├── test_sfp_webserver.py
    │   │   ├── test_sfp_whatcms.py
    │   │   ├── test_sfp_whois.py
    │   │   ├── test_sfp_whoisology.py
    │   │   ├── test_sfp_whoxy.py
    │   │   ├── test_sfp_wigle.py
    │   │   ├── test_sfp_wikileaks.py
    │   │   ├── test_sfp_wikipediaedits.py
    │   │   ├── test_sfp_xforce.py
    │   │   ├── test_sfp_yandexdns.py
    │   │   ├── test_sfp_zetalytics.py
    │   │   ├── test_sfp_zonefiles.py
    │   │   └── test_sfp_zoneh.py
    │   ├── spiderfoot/
    │   │   ├── test_spiderfootcorrelator.py
    │   │   ├── test_spiderfootdb.py
    │   │   ├── test_spiderfootevent.py
    │   │   ├── test_spiderfoothelpers.py
    │   │   ├── test_spiderfootplugin.py
    │   │   ├── test_spiderfoottarget.py
    │   │   └── test_spiderfootthreadpool.py
    │   ├── test_modules.py
    │   ├── test_spiderfoot.py
    │   ├── test_spiderfootcli.py
    │   ├── test_spiderfootscanner.py
    │   └── test_spiderfootwebui.py
    └── update-requirements

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
.git/

build
dist
*.egg-info
*.egg/
*.pyc
*.swp

venv/
cache/
log/
spiderfoot.db*
spiderfoot.test.db

__pycache__
htmlcov/
docs/


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
Please provide a description of the issue and any relevant error messages.

If you can provide an application stack trace that is even better.

What version of Python are you using?

What version of SpiderFoot are you using (stable release or Git `master` branch)?

You may also wish to check if your issue has been posted previously:

* https://github.com/smicallef/spiderfoot/issues



================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
name: "CodeQL"

on:
  push:
    branches:
      - master
  schedule:
    - cron: "26 16 * * 0"

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    strategy:
      fail-fast: true
      matrix:
        language: ["python"]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v1
        with:
          languages: ${{ matrix.language }}
      - name: Autobuild
        uses: github/codeql-action/autobuild@v1
      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v1


================================================
FILE: .github/workflows/tests.yaml
================================================
name: Tests

on:
  push:
    branches: master
  pull_request:
    branches: master

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        python-version: ["3.7", "3.8", "3.9", "3.10"]
        os: [ubuntu-latest, macos-latest]

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flake8 pytest
          pip install -r test/requirements.txt
      - name: Lint with flake8
        run: |
          # stop the build if there are Python Flake8 violations
          flake8 . --count --show-source --statistics
      - name: Test with pytest
        run: |
          python -m pytest -n auto --dist loadfile --ignore=test/integration/modules/ --durations=5 --cov-report term --cov=. .
      - uses: codecov/codecov-action@v1
        with:
          fail_ci_if_error: false
          verbose: true


================================================
FILE: .gitignore
================================================
# SpiderFoot specific #
#######################
/cache/
/log/
/spiderfoot.db*
passwd
spiderfoot.crt
spiderfoot.key

spiderfoot/static/node_modules/*

spiderfoot/static/node_modules/alertifyjs/*
spiderfoot/static/node_modules/alertifyjs/build/*
spiderfoot/static/node_modules/alertifyjs/build/css/*

!spiderfoot/static/node_modules/alertifyjs/
!spiderfoot/static/node_modules/alertifyjs/build/
!spiderfoot/static/node_modules/alertifyjs/build/alertify.min.js
!spiderfoot/static/node_modules/alertifyjs/build/css/
!spiderfoot/static/node_modules/alertifyjs/build/css/alertify.min.css

spiderfoot/static/node_modules/bootstrap/*
spiderfoot/static/node_modules/bootstrap/dist/*
spiderfoot/static/node_modules/bootstrap/dist/js/*
spiderfoot/static/node_modules/bootstrap/dist/css/*
spiderfoot/static/node_modules/bootstrap/dist/fonts/*

!spiderfoot/static/node_modules/bootstrap/
!spiderfoot/static/node_modules/bootstrap/dist/
!spiderfoot/static/node_modules/bootstrap/dist/js/
!spiderfoot/static/node_modules/bootstrap/dist/js/bootstrap.min.js
!spiderfoot/static/node_modules/bootstrap/dist/css/
!spiderfoot/static/node_modules/bootstrap/dist/css/bootstrap.min.css
!spiderfoot/static/node_modules/bootstrap/dist/fonts/
!spiderfoot/static/node_modules/bootstrap/dist/fonts/glyphicons-halflings-regular.woff
!spiderfoot/static/node_modules/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2

spiderfoot/static/node_modules/jquery/*
spiderfoot/static/node_modules/jquery/dist/*

!spiderfoot/static/node_modules/jquery/
!spiderfoot/static/node_modules/jquery/dist/
!spiderfoot/static/node_modules/jquery/dist/jquery.min.js

spiderfoot/static/node_modules/sigma/*
spiderfoot/static/node_modules/sigma/build/*
spiderfoot/static/node_modules/sigma/build/plugins/*

!spiderfoot/static/node_modules/sigma/
!spiderfoot/static/node_modules/sigma/build/
!spiderfoot/static/node_modules/sigma/build/sigma.min.js
!spiderfoot/static/node_modules/sigma/build/plugins/
!spiderfoot/static/node_modules/sigma/build/plugins/sigma.parsers.json.min.js
!spiderfoot/static/node_modules/sigma/build/plugins/sigma.plugins.dragNodes.min.js
!spiderfoot/static/node_modules/sigma/build/plugins/sigma.layout.forceAtlas2.min.js
!spiderfoot/static/node_modules/sigma/build/plugins/sigma.renderers.snapshot.min.js

spiderfoot/static/node_modules/tablesorter/*
spiderfoot/static/node_modules/tablesorter/dist/*
spiderfoot/static/node_modules/tablesorter/dist/js/*
spiderfoot/static/node_modules/tablesorter/dist/css/*
spiderfoot/static/node_modules/tablesorter/dist/js/extras/*

!spiderfoot/static/node_modules/tablesorter/
!spiderfoot/static/node_modules/tablesorter/dist/
!spiderfoot/static/node_modules/tablesorter/dist/css/
!spiderfoot/static/node_modules/tablesorter/dist/css/jquery.tablesorter.pager.min.css
!spiderfoot/static/node_modules/tablesorter/dist/css/theme.default.min.css
!spiderfoot/static/node_modules/tablesorter/dist/js/
!spiderfoot/static/node_modules/tablesorter/dist/js/jquery.tablesorter.min.js
!spiderfoot/static/node_modules/tablesorter/dist/js/jquery.tablesorter.widgets.min.js
!spiderfoot/static/node_modules/tablesorter/dist/js/extras/
!spiderfoot/static/node_modules/tablesorter/dist/js/extras/jquery.tablesorter.pager.min.js

spiderfoot/static/node_modules/d3/*

!spiderfoot/static/node_modules/d3/
!spiderfoot/static/node_modules/d3/d3.min.js

# Compiled source #
###################
__pycache__/
*.com
*.class
*.dll
*.exe
*.o
*.so
*.py[cod]
*$py.class

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

# Logs and databases #
######################
*.log
*.sqlite
*.db

# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
.*~
Icon?
ehthumbs.db
Thumbs.db

# Virtual environments #
########################
venv/
venv3/

# IDE #
#######
.idea
.vscode

# Test & Coverage Reports #
###########################
.coverage
coverage/
test/acceptance/results/
htmlcov/
report/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Documentation #
#################
docs/_build/


================================================
FILE: .pylintrc
================================================
[MASTER]

# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=

# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS

# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=

# Use multiple processes to speed up Pylint.
jobs=4

# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=

# Pickle collected data for later comparisons.
persistent=yes

# Specify a configuration file.
#rcfile=

# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages
suggestion-mode=yes

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no


[MESSAGES CONTROL]

# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=

# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=invalid-name,
        no-self-use,
        too-few-public-methods,
        too-many-ancestors,
        too-many-arguments,
        too-many-boolean-expressions,
        too-many-branches,
        too-many-instance-attributes,
        too-many-locals,
        too-many-nested-blocks,
        too-many-public-methods,
        too-many-return-statements,
        too-many-statements,

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member


[REPORTS]

# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)

# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=

# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio).You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
#output-format=text
output-format=parseable

# Tells whether to display a full report or only the messages
reports=no

# Activate the evaluation score.
score=yes


[REFACTORING]

# Maximum number of nested blocks for function / method body
max-nested-blocks=5

# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=optparse.Values,sys.exit


[BASIC]

# Regular expression matching correct argument names. Overrides argument-
# naming-style
argument-rgx=^[a-z][a-z0-9_]*$

# Regular expression matching correct attribute names. Overrides attr-naming-
# style
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$

# Bad variable names which should always be refused, separated by a comma
bad-names=

# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$

# Regular expression matching correct class names. Overrides class-naming-style
class-rgx=^_?[A-Z][a-zA-Z0-9]*$

# Naming style matching correct constant names
const-naming-style=UPPER_CASE

# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1

# Regular expression matching correct function names. Overrides function-
# naming-style
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$


# Good variable names which should always be accepted, separated by a comma
good-names=main,
           sf,
           _

# Include a hint for the correct naming format with invalid-name
include-naming-hint=no

# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style
inlinevar-rgx=^[a-z][a-z0-9_]*$

# Regular expression matching correct method names. Overrides method-naming-
# style
method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$

# Regular expression matching correct module names. Overrides module-naming-
# style
module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$

# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=

# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_

# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl

# Regular expression matching correct variable names. Overrides variable-
# naming-style
variable-rgx=^[a-z][a-z0-9_]*$


[SIMILARITIES]

# Ignore comments when computing similarities.
ignore-comments=yes

# Ignore docstrings when computing similarities.
ignore-docstrings=yes

# Ignore imports when computing similarities.
ignore-imports=no

# Minimum lines number of a similarity.
min-similarity-lines=4


[SPELLING]

# Limits count of emitted suggestions for spelling mistakes
max-spelling-suggestions=4

# Spelling dictionary name. Available dictionaries: en_US (myspell), en
# (aspell), en_AU (aspell), en_CA (aspell), en_GB (aspell).
spelling-dict=

# List of comma separated words that should not be checked.
spelling-ignore-words=

# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=

# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no


[LOGGING]

# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging


[FORMAT]

# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=

# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=(?x)(
  ^\s*(\#\ )?<?https?://\S+>?$|
  ^\s*(from\s+\S+\s+)?import\s+.+$)

# Number of spaces of indent required inside a hanging  or continued line.
indent-after-paren=4

# String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
# tab).
indent-string='    '

# Maximum number of characters on a single line.
max-line-length=120

# Maximum number of lines in a module
max-module-lines=1000

# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma

# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no

# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no


[MISCELLANEOUS]

# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
      XXX,
      TODO


[TYPECHECK]

# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager

# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=

# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes

# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes

# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local

# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=

# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes

# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1

# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1


[VARIABLES]

# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=

# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes

# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
          _cb

# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_

# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*|^ignored_|^unused_

# Tells whether we should check for unused import in __init__ files.
init-import=no

# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,io,builtins


[DESIGN]

# Maximum number of arguments for function / method
max-args=5

# Maximum number of attributes for a class (see R0902).
max-attributes=7

# Maximum number of boolean expressions in a if statement
max-bool-expr=5

# Maximum number of branch for function / method body
max-branches=12

# Maximum number of locals for function / method body
max-locals=15

# Maximum number of parents for a class (see R0901).
max-parents=7

# Maximum number of public methods for a class (see R0904).
max-public-methods=20

# Maximum number of return / yield for function / method body
max-returns=6

# Maximum number of statements in function / method body
max-statements=50

# Minimum number of public methods for a class (see R0903).
min-public-methods=2


[CLASSES]

# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
                      __new__,
                      setUp

# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
                  _fields,
                  _replace,
                  _source,
                  _make

# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls,
                            class_

# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs


[IMPORTS]

# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no

# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no

# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,
                   TERMIOS,
                   Bastion,
                   rexec,
                   sets

# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=

# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=

# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=

# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=

# Force import order to recognize a module as part of a third party library.
known-third-party=enchant


[EXCEPTIONS]

# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception,
                       BaseException,


================================================
FILE: Dockerfile
================================================
#
# Spiderfoot Dockerfile
#
# http://www.spiderfoot.net
#
# Written by: Michael Pellon <m@pellon.io>
# Updated by: Chandrapal <bnchandrapal@protonmail.com>
# Updated by: Steve Micallef <steve@binarypool.com>
# Updated by: Steve Bate <svc-spiderfoot@stevebate.net>
#    -> Inspired by https://github.com/combro2k/dockerfiles/tree/master/alpine-spiderfoot
#
# Usage:
#
#   sudo docker build -t spiderfoot .
#   sudo docker run -p 5001:5001 --security-opt no-new-privileges spiderfoot
#
# Using Docker volume for spiderfoot data
#
#   sudo docker run -p 5001:5001 -v /mydir/spiderfoot:/var/lib/spiderfoot spiderfoot
#
# Using SpiderFoot remote command line with web server
#
#   docker run --rm -it spiderfoot sfcli.py -s http://my.spiderfoot.host:5001/
#
# Running spiderfoot commands without web server (can optionally specify volume)
#
#   sudo docker run --rm spiderfoot sf.py -h
#
# Running a shell in the container for maintenance
#   sudo docker run -it --entrypoint /bin/sh spiderfoot
#
# Running spiderfoot unit tests in container
#
#   sudo docker build -t spiderfoot-test --build-arg REQUIREMENTS=test/requirements.txt .
#   sudo docker run --rm spiderfoot-test -m pytest --flake8 .

FROM alpine:3.12.4 AS build
ARG REQUIREMENTS=requirements.txt
RUN apk add --no-cache gcc git curl python3 python3-dev py3-pip swig tinyxml-dev \
 python3-dev musl-dev openssl-dev libffi-dev libxslt-dev libxml2-dev jpeg-dev \
 openjpeg-dev zlib-dev cargo rust
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin":$PATH
COPY $REQUIREMENTS requirements.txt ./
RUN ls
RUN echo "$REQUIREMENTS"
RUN pip3 install -U pip
RUN pip3 install -r "$REQUIREMENTS"



FROM alpine:3.13.0
WORKDIR /home/spiderfoot

# Place database and logs outside installation directory
ENV SPIDERFOOT_DATA /var/lib/spiderfoot
ENV SPIDERFOOT_LOGS /var/lib/spiderfoot/log
ENV SPIDERFOOT_CACHE /var/lib/spiderfoot/cache

# Run everything as one command so that only one layer is created
RUN apk --update --no-cache add python3 musl openssl libxslt tinyxml libxml2 jpeg zlib openjpeg \
    && addgroup spiderfoot \
    && adduser -G spiderfoot -h /home/spiderfoot -s /sbin/nologin \
               -g "SpiderFoot User" -D spiderfoot \
    && rm -rf /var/cache/apk/* \
    && rm -rf /lib/apk/db \
    && rm -rf /root/.cache \
    && mkdir -p $SPIDERFOOT_DATA || true \
    && mkdir -p $SPIDERFOOT_LOGS || true \
    && mkdir -p $SPIDERFOOT_CACHE || true \
    && chown spiderfoot:spiderfoot $SPIDERFOOT_DATA \
    && chown spiderfoot:spiderfoot $SPIDERFOOT_LOGS \
    && chown spiderfoot:spiderfoot $SPIDERFOOT_CACHE

COPY . .
COPY --from=build /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

USER spiderfoot

EXPOSE 5001

# Run the application.
ENTRYPOINT ["/opt/venv/bin/python"]
CMD ["sf.py", "-l", "0.0.0.0:5001"]


================================================
FILE: Dockerfile.full
================================================
#
# Spiderfoot Dockerfile (Full - includes all CLI tools, etc.)
#
# http://www.spiderfoot.net
#
# Written by: TheTechromancer
#

FROM python:3

# Install tools/dependencies from apt
RUN apt-get -y update && apt-get -y install nbtscan onesixtyone nmap

# Compile other tools from source
RUN mkdir /tools || true
WORKDIR /tools

# Install Golang tools
RUN apt-get -y update && apt-get -y install golang
ENV GOPATH="/go"
ENV PATH="$GOPATH/bin:$PATH"
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin"

# Install Ruby tools for WhatWeb
RUN apt-get -y update && apt-get -y install ruby ruby-dev bundler
# Install WhatWeb
RUN git clone https://github.com/urbanadventurer/WhatWeb \
    && gem install rchardet mongo json && cd /tools/WhatWeb \
    && bundle install && cd /tools

RUN groupadd spiderfoot \
    && useradd -m -g spiderfoot -d /home/spiderfoot -s /sbin/nologin \
    -c "SpiderFoot User" spiderfoot

# Install RetireJS
RUN apt remove -y cmdtest \
    && apt remove -y yarn \
    && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo 'deb https://dl.yarnpkg.com/debian/ stable main' |tee /etc/apt/sources.list.d/yarn.list \
    && apt-get update \
    && apt-get install yarn -y \
    && yarn install \
    && curl -fsSL https://deb.nodesource.com/setup_17.x | bash - \
    && apt-get install -y nodejs \
    && npm install -g retire

# Install Google Chrome the New Way (Not via apt-key)
RUN wget -qO - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/googlechrome-linux-keyring.gpg \
    && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list \
    && apt -y update && apt install --allow-unauthenticated -y google-chrome-stable

# Install Wappalyzer
RUN git clone https://github.com/AliasIO/wappalyzer.git \
    && cd wappalyzer \
    && yarn install && yarn run link

# Install Nuclei
RUN wget https://github.com/projectdiscovery/nuclei/releases/download/v2.6.5/nuclei_2.6.5_linux_amd64.zip \
    && unzip nuclei_2.6.5_linux_amd64.zip \
    && git clone https://github.com/projectdiscovery/nuclei-templates.git

# Install testssl.sh
RUN apt-get install -y bsdmainutils dnsutils coreutils
RUN git clone https://github.com/drwetter/testssl.sh.git

# Install Snallygaster and TruffleHog
RUN pip3 install snallygaster trufflehog

# Place database and logs outside installation directory
ENV SPIDERFOOT_DATA /var/lib/spiderfoot
ENV SPIDERFOOT_LOGS /var/lib/spiderfoot/log
ENV SPIDERFOOT_CACHE /var/lib/spiderfoot/cache

RUN mkdir -p $SPIDERFOOT_DATA || true \
    && mkdir -p $SPIDERFOOT_LOGS || true \
    && mkdir -p $SPIDERFOOT_CACHE || true \
    && chown spiderfoot:spiderfoot $SPIDERFOOT_DATA \
    && chown spiderfoot:spiderfoot $SPIDERFOOT_LOGS \
    && chown spiderfoot:spiderfoot $SPIDERFOOT_CACHE

WORKDIR /home/spiderfoot
COPY . .

ENV VIRTUAL_ENV=/opt/venv
RUN mkdir -p "$VIRTUAL_ENV" || true
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN python -m venv "$VIRTUAL_ENV"

ARG REQUIREMENTS=requirements.txt
COPY "$REQUIREMENTS" requirements.txt

RUN chown -R spiderfoot:spiderfoot /tools
RUN chown -R spiderfoot:spiderfoot "$VIRTUAL_ENV"
RUN chown -R spiderfoot:spiderfoot "/home/spiderfoot"

USER spiderfoot

RUN pip install -U pip
RUN pip install -r "$REQUIREMENTS"

# Install Python tools
RUN pip install dnstwist
# CMSeeK
WORKDIR /tools
RUN git clone https://github.com/Tuhinshubhra/CMSeeK && cd CMSeeK \
    && pip install -r requirements.txt && mkdir Results

# Install wafw00f
RUN git clone https://github.com/EnableSecurity/wafw00f \
    && cd wafw00f \
    && python3 setup.py install
WORKDIR /home/spiderfoot

EXPOSE 5001

# Run the application
CMD python -c 'from spiderfoot import SpiderFootDb; \
db = SpiderFootDb({"__database": "/var/lib/spiderfoot/spiderfoot.db"}); \
db.configSet({ \
    "sfp_tool_dnstwist:dnstwistpath": "/opt/venv/bin/dnstwist", \
    "sfp_tool_cmseek:cmseekpath": "/tools/CMSeeK/cmseek.py", \
    "sfp_tool_whatweb:whatweb_path": "/tools/WhatWeb/whatweb", \
    "sfp_tool_wafw00f:wafw00f_path": "/opt/venv/bin/wafw00f", \
    "sfp_tool_onesixtyone:onesixtyone_path": "/usr/bin/onesixtyone", \
    "sfp_tool_retirejs:retirejs_path": "/usr/bin/retire", \
    "sfp_tool_testsslsh:testsslsh_path": "/tools/testssl.sh/testssl.sh", \
    "sfp_tool_snallygaster:snallygaster_path": "/usr/local/bin/snallygaster", \
    "sfp_tool_trufflehog:trufflehog_path": "/usr/local/bin/trufflehog", \
    "sfp_tool_nuclei:nuclei_path": "/tools/nuclei", \
    "sfp_tool_nuclei:template_path": "/tools/nuclei-templates", \
    "sfp_tool_wappalyzer:wappalyzer_path": "/tools/wappalyzer/src/drivers/npm/cli.js", \
    "sfp_tool_nbtscan:nbtscan_path": "/usr/bin/nbtscan", \
    "sfp_tool_nmap:nmappath": "DISABLED_BECAUSE_NMAP_REQUIRES_ROOT_TO_WORK" \
})' || true && ./sf.py -l 0.0.0.0:5001


================================================
FILE: LICENSE
================================================
Copyright 2022 Steve Micallef <steve@binarypool.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
<a href="https://www.spiderfoot.net/r.php?u=aHR0cHM6Ly93d3cuc3BpZGVyZm9vdC5uZXQv&s=os_gh"><img src="https://www.spiderfoot.net/wp-content/themes/spiderfoot/img/spiderfoot-wide.png"></a>


[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/smicallef/spiderfoot/master/LICENSE)
[![Python Version](https://img.shields.io/badge/python-3.7+-green)](https://www.python.org)
[![Stable Release](https://img.shields.io/badge/version-4.0-blue.svg)](https://github.com/smicallef/spiderfoot/releases/tag/v4.0)
[![CI status](https://github.com/smicallef/spiderfoot/workflows/Tests/badge.svg)](https://github.com/smicallef/spiderfoot/actions?query=workflow%3A"Tests")
[![Last Commit](https://img.shields.io/github/last-commit/smicallef/spiderfoot)](https://github.com/smicallef/spiderfoot/commits/master)
[![Codecov](https://codecov.io/github/smicallef/spiderfoot/coverage.svg)](https://codecov.io/github/smicallef/spiderfoot)
[![Twitter Follow](https://img.shields.io/twitter/follow/spiderfoot?label=follow&style=social)](https://twitter.com/spiderfoot)
[![Discord](https://img.shields.io/discord/770524432464216074)](https://discord.gg/vyvztrG)

**SpiderFoot** is an open source intelligence (OSINT) automation tool. It integrates with just about every data source available and utilises a range of methods for data analysis, making that data easy to navigate. 

SpiderFoot has an embedded web-server for providing a clean and intuitive web-based interface but can also be used completely via the command-line.  It's written in **Python 3** and **MIT-licensed**.

<img src="https://www.spiderfoot.net/wp-content/uploads/2022/04/opensource-screenshot-v4.png" />

### FEATURES

- Web based UI or CLI
- Over 200 modules (see below)
- Python 3.7+
- YAML-configurable [correlation engine](/correlations/README.md) with [37 pre-defined rules](/correlations)
- CSV/JSON/GEXF export
- API key export/import
- SQLite back-end for custom querying
- Highly configurable
- Fully documented
- Visualisations
- TOR integration for dark web searching
- Dockerfile for Docker-based deployments
- Can call other tools like DNSTwist, Whatweb, Nmap and CMSeeK
- [Actively developed since 2012!](https://medium.com/@micallst/lessons-learned-from-my-10-year-open-source-project-4a4c8c2b4f64)

### WANT MORE?

Need more from SpiderFoot? Check out [SpiderFoot HX](https://www.spiderfoot.net/hx) for:
- 100% Cloud-based and managed for you
- Attack Surface Monitoring with change notifications by email, REST and Slack
- Multiple targets per scan
- Multi-user collaboration
- Authenticated and 2FA
- Investigations
- Customer support
- Third party tools pre-installed & configured
- Drive it with a fully RESTful API
- TOR integration built-in
- Screenshotting
- Bring your own Python SpiderFoot modules
- Feed scan data to Splunk, ElasticSearch and REST endpoints

See the full set of differences between SpiderFoot HX and the open source version [here](https://www.spiderfoot.net/open-source-vs-hx/).

### USES

SpiderFoot can be used offensively (e.g. in a red team exercise or penetration test) for reconnaissance of your target or defensively to gather information about what you or your organisation might have exposed over the Internet.

You can target the following entities in a SpiderFoot scan:

 - IP address
 - Domain/sub-domain name
 - Hostname
 - Network subnet (CIDR)
 - ASN
 - E-mail address
 - Phone number
 - Username
 - Person's name
 - Bitcoin address
 
SpiderFoot's 200+ modules feed each other in a publisher/subscriber model to ensure maximum data extraction to do things like:

- [Host/sub-domain/TLD enumeration/extraction](https://asciinema.org/a/295912)
- [Email address, phone number and human name extraction](https://asciinema.org/a/295947)
- [Bitcoin and Ethereum address extraction](https://asciinema.org/a/295957)
- [Check for susceptibility to sub-domain hijacking](https://asciinema.org/a/344377)
- DNS zone transfers
- [Threat intelligence and Blacklist queries](https://asciinema.org/a/295949)
- API integration with [SHODAN](https://asciinema.org/a/127601), [HaveIBeenPwned](https://asciinema.org/a/128731), [GreyNoise](https://asciinema.org/a/295943), AlienVault, SecurityTrails, etc.
- [Social media account enumeration](https://asciinema.org/a/295923)
- [S3/Azure/Digitalocean bucket enumeration/scraping](https://asciinema.org/a/295941)
- IP geo-location
- Web scraping, web content analysis
- [Image, document and binary file meta data analysis](https://asciinema.org/a/296274)
- Dark web searches
- [Port scanning and banner grabbing](https://asciinema.org/a/295939)
- [Data breach searches](https://asciinema.org/a/296145)
- So much more...

### INSTALLING & RUNNING

To install and run SpiderFoot, you need at least Python 3.7 and a number of Python libraries which you can install with `pip`. We recommend you install a packaged release since master will often have bleeding edge features and modules that aren't fully tested.

#### Stable build (packaged release):

```
 wget https://github.com/smicallef/spiderfoot/archive/v4.0.tar.gz
 tar zxvf v4.0.tar.gz
 cd spiderfoot-4.0
 pip3 install -r requirements.txt
 python3 ./sf.py -l 127.0.0.1:5001
```

#### Development build (cloning git master branch):

```
 git clone https://github.com/smicallef/spiderfoot.git
 cd spiderfoot
 pip3 install -r requirements.txt
 python3 ./sf.py -l 127.0.0.1:5001
```

Check out the [documentation](https://www.spiderfoot.net/documentation) and our [asciinema videos](https://asciinema.org/~spiderfoot) for more tutorials.

### COMMUNITY

Whether you're a contributor, user or just curious about SpiderFoot and OSINT in general, we'd love to have you join our community! SpiderFoot now has a [Discord server](https://discord.gg/vyvztrG) for seeking help from the community, requesting features or just general OSINT chit-chat.

### WRITING CORRELATION RULES

We have a comprehensive write-up and reference of the correlation rule-set introduced in SpiderFoot 4.0 [here](/correlations/README.md).

Also take a look at the [template.yaml](/correlations/template.yaml) file for a walk through. The existing [37 rules](/correlations) are also quite readable and good as starting points for additional rules.

### MODULES / INTEGRATIONS

SpiderFoot has over 200 modules, most of which *don't require API keys*, and many of those that do require API keys *have a free tier*.

| Name     | Description | Type   |
|:---------| :-----------|:-------|
[AbstractAPI](https://app.abstractapi.com/)|Look up domain, phone and IP address information from AbstractAPI.|Tiered API
[abuse.ch](https://www.abuse.ch)|Check if a host/domain, IP address or netblock is malicious according to Abuse.ch.|Free API
[AbuseIPDB](https://www.abuseipdb.com)|Check if an IP address is malicious according to AbuseIPDB.com blacklist.|Tiered API
[Abusix Mail Intelligence](https://abusix.org/)|Check if a netblock or IP address is in the Abusix Mail Intelligence blacklist.|Tiered API
Account Finder|Look for possible associated accounts on over 500 social and other websites such as Instagram, Reddit, etc.|Internal
[AdBlock Check](https://adblockplus.org/)|Check if linked pages would be blocked by AdBlock Plus.|Tiered API
[AdGuard DNS](https://adguard.com/)|Check if a host would be blocked by AdGuard DNS.|Free API
[Ahmia](https://ahmia.fi/)|Search Tor 'Ahmia' search engine for mentions of the target.|Free API
[AlienVault IP Reputation](https://cybersecurity.att.com/)|Check if an IP or netblock is malicious according to the AlienVault IP Reputation database.|Free API
[AlienVault OTX](https://otx.alienvault.com/)|Obtain information from AlienVault Open Threat Exchange (OTX)|Tiered API
[Amazon S3 Bucket Finder](https://aws.amazon.com/s3/)|Search for potential Amazon S3 buckets associated with the target and attempt to list their contents.|Free API
[Apple iTunes](https://itunes.apple.com/)|Search Apple iTunes for mobile apps.|Free API
[Archive.org](https://archive.org/)|Identifies historic versions of interesting files/pages from the Wayback Machine.|Free API
[ARIN](https://www.arin.net/)|Queries ARIN registry for contact information.|Free API
[Azure Blob Finder](https://azure.microsoft.com/en-in/services/storage/blobs/)|Search for potential Azure blobs associated with the target and attempt to list their contents.|Free API
Base64 Decoder|Identify Base64-encoded strings in URLs, often revealing interesting hidden information.|Internal
[BGPView](https://bgpview.io/)|Obtain network information from BGPView API.|Free API
Binary String Extractor|Attempt to identify strings in binary content.|Internal
[BinaryEdge](https://www.binaryedge.io/)|Obtain information from BinaryEdge.io Internet scanning systems, including breaches, vulnerabilities, torrents and passive DNS.|Tiered API
[Bing (Shared IPs)](https://www.bing.com/)|Search Bing for hosts sharing the same IP.|Tiered API
[Bing](https://www.bing.com/)|Obtain information from bing to identify sub-domains and links.|Tiered API
Bitcoin Finder|Identify bitcoin addresses in scraped webpages.|Internal
[Bitcoin Who's Who](https://bitcoinwhoswho.com/)|Check for Bitcoin addresses against the Bitcoin Who's Who database of suspect/malicious addresses.|Tiered API
[BitcoinAbuse](https://www.bitcoinabuse.com/)|Check Bitcoin addresses against the bitcoinabuse.com database of suspect/malicious addresses.|Free API
[Blockchain](https://www.blockchain.com/)|Queries blockchain.info to find the balance of identified bitcoin wallet addresses.|Free API
[blocklist.de](http://www.blocklist.de/en/index.html)|Check if a netblock or IP is malicious according to blocklist.de.|Free API
[BotScout](https://botscout.com/)|Searches BotScout.com's database of spam-bot IP addresses and e-mail addresses.|Tiered API
[botvrij.eu](https://botvrij.eu/)|Check if a domain is malicious according to botvrij.eu.|Free API
[BuiltWith](https://builtwith.com/)|Query BuiltWith.com's Domain API for information about your target's web technology stack, e-mail addresses and more.|Tiered API
[C99](https://api.c99.nl/)|Queries the C99 API which offers various data (geo location, proxy detection, phone lookup, etc).|Commercial API
[CallerName](http://callername.com/)|Lookup US phone number location and reputation information.|Free API
[Censys](https://censys.io/)|Obtain host information from Censys.io.|Tiered API
[Certificate Transparency](https://crt.sh/)|Gather hostnames from historical certificates in crt.sh.|Free API
[CertSpotter](https://sslmate.com/certspotter/)|Gather information about SSL certificates from SSLMate CertSpotter API.|Tiered API
[CINS Army List](https://cinsscore.com/)|Check if a netblock or IP address is malicious according to Collective Intelligence Network Security (CINS) Army list.|Free API
[CIRCL.LU](https://www.circl.lu/)|Obtain information from CIRCL.LU's Passive DNS and Passive SSL databases.|Free API
[CleanBrowsing.org](https://cleanbrowsing.org/)|Check if a host would be blocked by CleanBrowsing.org DNS content filters.|Free API
[CleanTalk Spam List](https://cleantalk.org)|Check if a netblock or IP address is on CleanTalk.org's spam IP list.|Free API
[Clearbit](https://clearbit.com/)|Check for names, addresses, domains and more based on lookups of e-mail addresses on clearbit.com.|Tiered API
[CloudFlare DNS](https://www.cloudflare.com/)|Check if a host would be blocked by CloudFlare DNS.|Free API
[CoinBlocker Lists](https://zerodot1.gitlab.io/CoinBlockerListsWeb/)|Check if a domain appears on CoinBlocker lists.|Free API
[CommonCrawl](http://commoncrawl.org/)|Searches for URLs found through CommonCrawl.org.|Free API
[Comodo Secure DNS](https://www.comodo.com/secure-dns/)|Check if a host would be blocked by Comodo Secure DNS.|Tiered API
Company Name Extractor|Identify company names in any obtained data.|Internal
Cookie Extractor|Extract Cookies from HTTP headers.|Internal
Country Name Extractor|Identify country names in any obtained data.|Internal
Credit Card Number Extractor|Identify Credit Card Numbers in any data|Internal
[Crobat API](https://sonar.omnisint.io/)|Search Crobat API for subdomains.|Free API
Cross-Referencer|Identify whether other domains are associated ('Affiliates') of the target by looking for links back to the target site(s).|Internal
[CRXcavator](https://crxcavator.io/)|Search CRXcavator for Chrome extensions.|Free API
Custom Threat Feed|Check if a host/domain, netblock, ASN or IP is malicious according to your custom feed.|Internal
[CyberCrime-Tracker.net](https://cybercrime-tracker.net/)|Check if a host/domain or IP address is malicious according to CyberCrime-Tracker.net.|Free API
[Debounce](https://debounce.io/)|Check whether an email is disposable|Free API
[Dehashed](https://www.dehashed.com/)|Gather breach data from Dehashed API.|Commercial API
[Digital Ocean Space Finder](https://www.digitalocean.com/products/spaces/)|Search for potential Digital Ocean Spaces associated with the target and attempt to list their contents.|Free API
DNS Brute-forcer|Attempts to identify hostnames through brute-forcing common names and iterations.|Internal
DNS Common SRV|Attempts to identify hostnames through brute-forcing common DNS SRV records.|Internal
[DNS for Family](https://dnsforfamily.com/)|Check if a host would be blocked by DNS for Family.|Free API
DNS Look-aside|Attempt to reverse-resolve the IP addresses next to your target to see if they are related.|Internal
DNS Raw Records|Retrieves raw DNS records such as MX, TXT and others.|Internal
DNS Resolver|Resolves hosts and IP addresses identified, also extracted from raw content.|Internal
DNS Zone Transfer|Attempts to perform a full DNS zone transfer.|Internal
[DNSDB](https://www.farsightsecurity.com)|Query FarSight's DNSDB for historical and passive DNS data.|Tiered API
[DNSDumpster](https://dnsdumpster.com/)|Passive subdomain enumeration using HackerTarget's DNSDumpster|Free API
[DNSGrep](https://opendata.rapid7.com/)|Obtain Passive DNS information from Rapid7 Sonar Project using DNSGrep API.|Free API
[DroneBL](https://dronebl.org/)|Query the DroneBL database for open relays, open proxies, vulnerable servers, etc.|Free API
[DuckDuckGo](https://duckduckgo.com/)|Query DuckDuckGo's API for descriptive information about your target.|Free API
E-Mail Address Extractor|Identify e-mail addresses in any obtained data.|Internal
[EmailCrawlr](https://emailcrawlr.com/)|Search EmailCrawlr for email addresses and phone numbers associated with a domain.|Tiered API
[EmailFormat](https://www.email-format.com/)|Look up e-mail addresses on email-format.com.|Free API
[EmailRep](https://emailrep.io/)|Search EmailRep.io for email address reputation.|Tiered API
[Emerging Threats](https://rules.emergingthreats.net/)|Check if a netblock or IP address is malicious according to EmergingThreats.net.|Free API
Error String Extractor|Identify common error messages in content like SQL errors, etc.|Internal
Ethereum Address Extractor|Identify ethereum addresses in scraped webpages.|Internal
[Etherscan](https://etherscan.io)|Queries etherscan.io to find the balance of identified ethereum wallet addresses.|Free API
File Metadata Extractor|Extracts meta data from documents and images.|Internal
[Flickr](https://www.flickr.com/)|Search Flickr for domains, URLs and emails related to the specified domain.|Free API
[Focsec](https://focsec.com/)|Look up IP address information from Focsec.|Tiered API
[FortiGuard Antispam](https://www.fortiguard.com/)|Check if an IP address is malicious according to FortiGuard Antispam.|Free API
[Fraudguard](https://fraudguard.io/)|Obtain threat information from Fraudguard.io|Tiered API
[F-Secure Riddler.io](https://riddler.io/)|Obtain network information from F-Secure Riddler.io API.|Commercial API
[FullContact](https://www.fullcontact.com)|Gather domain and e-mail information from FullContact.com API.|Tiered API
[FullHunt](https://fullhunt.io/)|Identify domain attack surface using FullHunt API.|Tiered API
[Github](https://github.com/)|Identify associated public code repositories on Github.|Free API
[GLEIF](https://search.gleif.org/)|Look up company information from Global Legal Entity Identifier Foundation (GLEIF).|Tiered API
[Google Maps](https://cloud.google.com/maps-platform/)|Identifies potential physical addresses and latitude/longitude coordinates.|Tiered API
[Google Object Storage Finder](https://cloud.google.com/storage)|Search for potential Google Object Storage buckets associated with the target and attempt to list their contents.|Free API
[Google SafeBrowsing](https://developers.google.com/safe-browsing/v4/lookup-api)|Check if the URL is included on any of the Safe Browsing lists.|Free API
[Google](https://developers.google.com/custom-search)|Obtain information from the Google Custom Search API to identify sub-domains and links.|Tiered API
[Gravatar](https://secure.gravatar.com/)|Retrieve user information from Gravatar API.|Free API
[Grayhat Warfare](https://buckets.grayhatwarfare.com/)|Find bucket names matching the keyword extracted from a domain from Grayhat API.|Tiered API
[Greensnow](https://greensnow.co/)|Check if a netblock or IP address is malicious according to greensnow.co.|Free API
[grep.app](https://grep.app/)|Search grep.app API for links and emails related to the specified domain.|Free API
[GreyNoise Community](https://greynoise.io/)|Obtain IP enrichment data from GreyNoise Community API|Tiered API
[GreyNoise](https://greynoise.io/)|Obtain IP enrichment data from GreyNoise|Tiered API
[HackerOne (Unofficial)](http://www.nobbd.de/)|Check external vulnerability scanning/reporting service h1.nobbd.de to see if the target is listed.|Free API
[HackerTarget](https://hackertarget.com/)|Search HackerTarget.com for hosts sharing the same IP.|Free API
Hash Extractor|Identify MD5 and SHA hashes in web content, files and more.|Internal
[HaveIBeenPwned](https://haveibeenpwned.com/)|Check HaveIBeenPwned.com for hacked e-mail addresses identified in breaches.|Commercial API
Hosting Provider Identifier|Find out if any IP addresses identified fall within known 3rd party hosting ranges, e.g. Amazon, Azure, etc.|Internal
[Host.io](https://host.io)|Obtain information about domain names from host.io.|Tiered API
Human Name Extractor|Attempt to identify human names in fetched content.|Internal
[Hunter.io](https://hunter.io/)|Check for e-mail addresses and names on hunter.io.|Tiered API
[Hybrid Analysis](https://www.hybrid-analysis.com)|Search Hybrid Analysis for domains and URLs related to the target.|Free API
IBAN Number Extractor|Identify International Bank Account Numbers (IBANs) in any data.|Internal
[Iknowwhatyoudownload.com](https://iknowwhatyoudownload.com/en/peer/)|Check iknowwhatyoudownload.com for IP addresses that have been using torrents.|Tiered API
[IntelligenceX](https://intelx.io/)|Obtain information from IntelligenceX about identified IP addresses, domains, e-mail addresses and phone numbers.|Tiered API
Interesting File Finder|Identifies potential files of interest, e.g. office documents, zip files.|Internal
[Internet Storm Center](https://isc.sans.edu)|Check if an IP address is malicious according to SANS ISC.|Free API
[ipapi.co](https://ipapi.co/)|Queries ipapi.co to identify geolocation of IP Addresses using ipapi.co API|Tiered API
[ipapi.com](https://ipapi.com/)|Queries ipapi.com to identify geolocation of IP Addresses using ipapi.com API|Tiered API
[IPInfo.io](https://ipinfo.io)|Identifies the physical location of IP addresses identified using ipinfo.io.|Tiered API
[IPQualityScore](https://www.ipqualityscore.com/)|Determine if target is malicious using IPQualityScore API|Tiered API
[ipregistry](https://ipregistry.co/)|Query the ipregistry.co database for reputation and geo-location.|Tiered API
[ipstack](https://ipstack.com/)|Identifies the physical location of IP addresses identified using ipstack.com.|Tiered API
[JsonWHOIS.com](https://jsonwhois.com)|Search JsonWHOIS.com for WHOIS records associated with a domain.|Tiered API
Junk File Finder|Looks for old/temporary and other similar files.|Internal
[Keybase](https://keybase.io/)|Obtain additional information about domain names and identified usernames.|Free API
[Koodous](https://koodous.com/apks/)|Search Koodous for mobile apps.|Tiered API
[LeakIX](https://leakix.net/)|Search LeakIX for host data leaks, open ports, software and geoip.|Free API
[Leak-Lookup](https://leak-lookup.com/)|Searches Leak-Lookup.com's database of breaches.|Free API
[Maltiverse](https://maltiverse.com)|Obtain information about any malicious activities involving IP addresses|Free API
[MalwarePatrol](https://www.malwarepatrol.net/)|Searches malwarepatrol.net's database of malicious URLs/IPs.|Tiered API
[MetaDefender](https://metadefender.opswat.com/)|Search MetaDefender API for IP address and domain IP reputation.|Tiered API
[Mnemonic PassiveDNS](https://www.mnemonic.no)|Obtain Passive DNS information from PassiveDNS.mnemonic.no.|Free API
[multiproxy.org Open Proxies](https://multiproxy.org/)|Check if an IP address is an open proxy according to multiproxy.org open proxy list.|Free API
[MySpace](https://myspace.com/)|Gather username and location from MySpace.com profiles.|Free API
[NameAPI](https://www.nameapi.org/)|Check whether an email is disposable|Tiered API
[NetworksDB](https://networksdb.io/)|Search NetworksDB.io API for IP address and domain information.|Tiered API
[NeutrinoAPI](https://www.neutrinoapi.com/)|Search NeutrinoAPI for phone location information, IP address information, and host reputation.|Tiered API
[numverify](http://numverify.com/)|Lookup phone number location and carrier information from numverify.com.|Tiered API
[Onion.link](https://onion.link/)|Search Tor 'Onion City' search engine for mentions of the target domain using Google Custom Search.|Free API
[Onionsearchengine.com](https://as.onionsearchengine.com)|Search Tor onionsearchengine.com for mentions of the target domain.|Free API
[Onyphe](https://www.onyphe.io)|Check Onyphe data (threat list, geo-location, pastries, vulnerabilities)  about a given IP.|Tiered API
[Open Bug Bounty](https://www.openbugbounty.org/)|Check external vulnerability scanning/reporting service openbugbounty.org to see if the target is listed.|Free API
[OpenCorporates](https://opencorporates.com)|Look up company information from OpenCorporates.|Tiered API
[OpenDNS](https://www.opendns.com/)|Check if a host would be blocked by OpenDNS.|Free API
[OpenNIC DNS](https://www.opennic.org/)|Resolves host names in the OpenNIC alternative DNS system.|Free API
[OpenPhish](https://openphish.com/)|Check if a host/domain is malicious according to OpenPhish.com.|Free API
[OpenStreetMap](https://www.openstreetmap.org/)|Retrieves latitude/longitude coordinates for physical addresses from OpenStreetMap API.|Free API
Page Information|Obtain information about web pages (do they take passwords, do they contain forms, etc.)|Internal
[PasteBin](https://pastebin.com/)|PasteBin search (via Google Search API) to identify related content.|Tiered API
PGP Key Servers|Look up domains and e-mail addresses in PGP public key servers.|Internal
[PhishStats](https://phishstats.info/)|Check if a netblock or IP address is malicious according to PhishStats.|Free API
[PhishTank](https://phishtank.com/)|Check if a host/domain is malicious according to PhishTank.|Free API
Phone Number Extractor|Identify phone numbers in scraped webpages.|Internal
Port Scanner - TCP|Scans for commonly open TCP ports on Internet-facing systems.|Internal
[Project Honey Pot](https://www.projecthoneypot.org/)|Query the Project Honey Pot database for IP addresses.|Free API
[ProjectDiscovery Chaos](https://chaos.projectdiscovery.io)|Search for hosts/subdomains using chaos.projectdiscovery.io|Commercial API
[Psbdmp](https://psbdmp.cc/)|Check psbdmp.cc (PasteBin Dump) for potentially hacked e-mails and domains.|Free API
[Pulsedive](https://pulsedive.com/)|Obtain information from Pulsedive's API.|Tiered API
[PunkSpider](https://punkspider.io/)|Check the QOMPLX punkspider.io service to see if the target is listed as vulnerable.|Free API
[Quad9](https://quad9.net/)|Check if a host would be blocked by Quad9 DNS.|Free API
[ReverseWhois](https://www.reversewhois.io/)|Reverse Whois lookups using reversewhois.io.|Free API
[RIPE](https://www.ripe.net/)|Queries the RIPE registry (includes ARIN data) to identify netblocks and other info.|Free API
[RiskIQ](https://community.riskiq.com/)|Obtain information from RiskIQ's (formerly PassiveTotal) Passive DNS and Passive SSL databases.|Tiered API
[Robtex](https://www.robtex.com/)|Search Robtex.com for hosts sharing the same IP.|Free API
[searchcode](https://searchcode.com/)|Search searchcode for code repositories mentioning the target domain.|Free API
[SecurityTrails](https://securitytrails.com/)|Obtain Passive DNS and other information from SecurityTrails|Tiered API
[Seon](https://seon.io/)|Queries seon.io to gather intelligence about IP Addresses, email addresses, and phone numbers|Commercial API
[SHODAN](https://www.shodan.io/)|Obtain information from SHODAN about identified IP addresses.|Tiered API
Similar Domain Finder|Search various sources to identify similar looking domain names, for instance squatted domains.|Internal
[Skymem](http://www.skymem.info/)|Look up e-mail addresses on Skymem.|Free API
[SlideShare](https://www.slideshare.net)|Gather name and location from SlideShare profiles.|Free API
[Snov](https://snov.io/)|Gather available email IDs from identified domains|Tiered API
[Social Links](https://sociallinks.io/)|Queries SocialLinks.io to gather intelligence from social media platforms and dark web.|Commercial API
[Social Media Profile Finder](https://developers.google.com/custom-search)|Tries to discover the social media profiles for human names identified.|Tiered API
Social Network Identifier|Identify presence on social media networks such as LinkedIn, Twitter and others.|Internal
[SORBS](http://www.sorbs.net/)|Query the SORBS database for open relays, open proxies, vulnerable servers, etc.|Free API
[SpamCop](https://www.spamcop.net/)|Check if a netblock or IP address is in the SpamCop database.|Free API
[Spamhaus Zen](https://www.spamhaus.org/)|Check if a netblock or IP address is in the Spamhaus Zen database.|Free API
[spur.us](https://spur.us/)|Obtain information about any malicious activities involving IP addresses found|Commercial API
[SpyOnWeb](http://spyonweb.com/)|Search SpyOnWeb for hosts sharing the same IP address, Google Analytics code, or Google Adsense code.|Tiered API
SSL Certificate Analyzer|Gather information about SSL certificates used by the target's HTTPS sites.|Internal
[StackOverflow](https://www.stackexchange.com)|Search StackOverflow for any mentions of a target domain. Returns potentially related information.|Tiered API
[Steven Black Hosts](https://github.com/StevenBlack/hosts)|Check if a domain is malicious (malware or adware) according to Steven Black Hosts list.|Free API
Strange Header Identifier|Obtain non-standard HTTP headers returned by web servers.|Internal
Subdomain Takeover Checker|Check if affiliated subdomains are vulnerable to takeover.|Internal
[Sublist3r PassiveDNS](https://api.sublist3r.com)|Passive subdomain enumeration using Sublist3r's API|Free API
[SURBL](http://www.surbl.org/)|Check if a netblock, IP address or domain is in the SURBL blacklist.|Free API
[Talos Intelligence](https://talosintelligence.com/)|Check if a netblock or IP address is malicious according to TalosIntelligence.|Free API
[TextMagic](https://www.textmagic.com/)|Obtain phone number type from TextMagic API|Tiered API
[Threat Jammer](https://threatjammer.com)|Check if an IP address is malicious according to ThreatJammer.com|Tiered API
[ThreatCrowd](https://www.threatcrowd.org)|Obtain information from ThreatCrowd about identified IP addresses, domains and e-mail addresses.|Free API
[ThreatFox](https://threatfox.abuse.ch)|Check if an IP address is malicious according to ThreatFox.|Free API
[ThreatMiner](https://www.threatminer.org/)|Obtain information from ThreatMiner's database for passive DNS and threat intelligence.|Free API
TLD Searcher|Search all Internet TLDs for domains with the same name as the target (this can be very slow.)|Internal
[Tool - CMSeeK]([https://github.com/Tuhinshubhra/CMSeeK](https://github.com/Tuhinshubhra/CMSeeK))|Identify what Content Management System (CMS) might be used.|Tool
[Tool - DNSTwist]([https://github.com/elceef/dnstwist](https://github.com/elceef/dnstwist))|Identify bit-squatting, typo and other similar domains to the target using a local DNSTwist installation.|Tool
[Tool - nbtscan]([http://www.unixwiz.net/tools/nbtscan.html](http://www.unixwiz.net/tools/nbtscan.html))|Scans for open NETBIOS nameservers on your target's network.|Tool
[Tool - Nmap]([https://nmap.org/](https://nmap.org/))|Identify what Operating System might be used.|Tool
[Tool - Nuclei]([https://nuclei.projectdiscovery.io/](https://nuclei.projectdiscovery.io/))|Fast and customisable vulnerability scanner.|Tool
[Tool - onesixtyone]([https://github.com/trailofbits/onesixtyone](https://github.com/trailofbits/onesixtyone))|Fast scanner to find publicly exposed SNMP services.|Tool
[Tool - Retire.js]([http://retirejs.github.io/retire.js/](http://retirejs.github.io/retire.js/))|Scanner detecting the use of JavaScript libraries with known vulnerabilities|Tool
[Tool - snallygaster]([https://github.com/hannob/snallygaster](https://github.com/hannob/snallygaster))|Finds file leaks and other security problems on HTTP servers.|Tool
[Tool - testssl.sh]([https://testssl.sh](https://testssl.sh))|Identify various TLS/SSL weaknesses, including Heartbleed, CRIME and ROBOT.|Tool
[Tool - TruffleHog]([https://github.com/trufflesecurity/truffleHog](https://github.com/trufflesecurity/truffleHog))|Searches through git repositories for high entropy strings and secrets, digging deep into commit history.|Tool
[Tool - WAFW00F]([https://github.com/EnableSecurity/wafw00f](https://github.com/EnableSecurity/wafw00f))|Identify what web application firewall (WAF) is in use on the specified website.|Tool
[Tool - Wappalyzer]([https://www.wappalyzer.com/](https://www.wappalyzer.com/))|Wappalyzer indentifies technologies on websites.|Tool
[Tool - WhatWeb]([https://github.com/urbanadventurer/whatweb](https://github.com/urbanadventurer/whatweb))|Identify what software is in use on the specified website.|Tool
[TOR Exit Nodes](https://metrics.torproject.org/)|Check if an IP adddress or netblock appears on the Tor Metrics exit node list.|Free API
[TORCH](https://torchsearch.wordpress.com/)|Search Tor 'TORCH' search engine for mentions of the target domain.|Free API
[Trashpanda](https://got-hacked.wtf)|Queries Trashpanda to gather intelligence about mentions of target in pastesites|Tiered API
[Trumail](https://trumail.io/)|Check whether an email is disposable|Free API
[Twilio](https://www.twilio.com/)|Obtain information from Twilio about phone numbers. Ensure you have the Caller Name add-on installed in Twilio.|Tiered API
[Twitter](https://twitter.com/)|Gather name and location from Twitter profiles.|Free API
[UCEPROTECT](http://www.uceprotect.net/)|Check if a netblock or IP address is in the UCEPROTECT database.|Free API
[URLScan.io](https://urlscan.io/)|Search URLScan.io cache for domain information.|Free API
[Venmo](https://venmo.com/)|Gather user information from Venmo API.|Free API
[ViewDNS.info](https://viewdns.info/)|Identify co-hosted websites and perform reverse Whois lookups using ViewDNS.info.|Tiered API
[VirusTotal](https://www.virustotal.com/)|Obtain information from VirusTotal about identified IP addresses.|Tiered API
[VoIP Blacklist (VoIPBL)](https://voipbl.org/)|Check if an IP address or netblock is malicious according to VoIP Blacklist (VoIPBL).|Free API
[VXVault.net](http://vxvault.net/)|Check if a domain or IP address is malicious according to VXVault.net.|Free API
Web Analytics Extractor|Identify web analytics IDs in scraped webpages and DNS TXT records.|Internal
Web Framework Identifier|Identify the usage of popular web frameworks like jQuery, YUI and others.|Internal
Web Server Identifier|Obtain web server banners to identify versions of web servers being used.|Internal
Web Spider|Spidering of web-pages to extract content for searching.|Internal
[WhatCMS](https://whatcms.org/)|Check web technology using WhatCMS.org API.|Tiered API
[Whoisology](https://whoisology.com/)|Reverse Whois lookups using Whoisology.com.|Commercial API
Whois|Perform a WHOIS look-up on domain names and owned netblocks.|Internal
[Whoxy](https://www.whoxy.com/)|Reverse Whois lookups using Whoxy.com.|Commercial API
[WiGLE](https://wigle.net/)|Query WiGLE to identify nearby WiFi access points.|Free API
[Wikileaks](https://wikileaks.org/)|Search Wikileaks for mentions of domain names and e-mail addresses.|Free API
[Wikipedia Edits](https://www.wikipedia.org/)|Identify edits to Wikipedia articles made from a given IP address or username.|Free API
[XForce Exchange](https://exchange.xforce.ibmcloud.com/)|Obtain IP reputation and passive DNS information from IBM X-Force Exchange.|Tiered API
[Yandex DNS](https://yandex.com/)|Check if a host would be blocked by Yandex DNS.|Free API
[Zetalytics](https://zetalytics.com/)|Query the Zetalytics database for hosts on your target domain(s).|Tiered API
[ZoneFile.io](https://zonefiles.io)|Search ZoneFiles.io Domain query API for domain information.|Tiered API
[Zone-H Defacement Check](https://zone-h.org/)|Check if a hostname/domain appears on the zone-h.org 'special defacements' RSS feed.|Free API

### DOCUMENTATION

Read more at the [project website](https://www.spiderfoot.net/r.php?u=aHR0cHM6Ly93d3cuc3BpZGVyZm9vdC5uZXQv&s=os_gh), including more complete documentation, blog posts with tutorials/guides, plus information about [SpiderFoot HX](https://www.spiderfoot.net/r.php?u=aHR0cHM6Ly93d3cuc3BpZGVyZm9vdC5uZXQvaHgvCg==&s=os_gh).

Latest updates announced on [Twitter](https://twitter.com/spiderfoot).


================================================
FILE: THANKYOU
================================================
These people are owed some credit for their contributions to SpiderFoot, be it
bug fixes or new functionality. Thank you!

- Brendan Coles (https://github.com/bcoles)
    - Second highest contributor to the project
    - Tons of modules, fixes and established the whole testing framework
    - Too many contributions to list here, see https://github.com/smicallef/spiderfoot/pulls?q=is%3Apr+author%3Abcoles+is%3Aclosed

- Krishnasis Mandal (https://github.com/krishnasism)
    - Many modules, see https://github.com/smicallef/spiderfoot/pulls?q=is%3Apr+author%3Akrishnasism+is%3Aclosed

- Steve Bate (https://github.com/steve-bate)
    - Multiple bug fixes, performance and quality improvements

- fallingcubes (https://github.com/fallingcubes)
    - Use of multiprocessing instead of threading for running multiple scans simultaneously

- Counter Intrusive Technologies (https://github.com/counterintrusive)
    - sfp_citadel updates

- Dhiraj Mishra (https://github.com/RootUp)
    - Created the sfp_h1nobbdde module

- Chris Weber (http://www.casaba.com/blog/author/chris/)
    - Many recommendations for improvement

- Henri Salo (https://github.com/fgeek)
    - Identified XSS issues (issue #29)

- MarioVilas (https://github.com/MarioVilas)
    - Contributed a fix for CSV exports (issue #35)

- johnnykv (https://github.com/johnnykv)
    - Contributed improved pip instructions

- Russ McRee (@holisticinfosec)
    - Identified XSS/CSRF issues

- Andrea De Pasquale (https://github.com/adepasquale)
    - Cache directory fix

- Viyat Bhalodia (https://github.com/delta24)
    - Prettied up README.md

- Gormogon (https://github.com/Gormogon)
    - Huge code clean up for PEP 8 compliance

- Lin Zhemin (https://github.com/miaoski)
    - Added the ability to use a configurable document root

- Micah Hoffman (https://github.com/WebBreacher)
    - Comprehensive list of URLs for identifying account usage in modules/sfp_accounts.py

- Michael Pellon (https://github.com/mpellon)
    - Providing a Dockerfile

- HackershubNL (https://github.com/HackershubNL)
    - Contributions towards authentication functionality

- Mathew Woodyard (https://github.com/woodrad)
    - Bad Packets module improvements


================================================
FILE: VERSION
================================================
SpiderFoot 4.0.0


================================================
FILE: correlations/README.md
================================================
## Background

SpiderFoot’s goal is to automate OSINT collection and analysis to the greatest extent possible. Since its inception, SpiderFoot has heavily focused on automating OSINT collection and entity extraction, but the automation of common analysis tasks -- beyond some reporting and visualisations -- has been left entirely to the user. The meant that the strength of SpiderFoot's data collection capabilities has sometimes been its weakness since with so much data collected, users have often needed to export it and use other tools to weed out data of interest.

## Introducing Correlations

We started tackling this analysis gap with the launch of SpiderFoot HX in 2019 through the introduction of the "Correlations" feature. This feature was represented by some 30 "correlation rules" that ran with each scan, analyzing data and presenting results reflecting SpiderFoot's opinionated view on what may be important or interesting. Here are a few of those rules as examples:
* Hosts/IPs reported as malicious by multiple data sources
* Outlier web servers (can be an indication of shadow IT)
* Databases exposed on the Internet
* Open ports revealing software versions
* and many more.

With the release of SpiderFoot 4.0 we wanted to bring this capability from SpiderFoot HX to the community, but also re-imagine it at the same time so that the community might not simply run rules we provide, but also write their own correlation rules and contribute them back. We also hope that just as with modules, we see a long list of contributions made in the years ahead so that all may benefit.

With that said, let's get into what these rules look like and how to write one.

## Key concepts

### YAML
The rules themselves are written in YAML. Why YAML? It’s easy to read, write, allows for comments and is increasingly commonplace in many modern tools.

### Rule structure
The simplest way to think of a SpiderFoot correlation rule is like a simple database query that consists of a few sections:
1. Defining the rule itself (`id`, `version` and `meta` sections).
2. Stating what you'd like to extract from the scan results (`collections` section).
3. Grouping that data in some way (`aggregation` section; optional).
3. Performing some analysis over that data in some way (`analysis` section; optional).
4. Presenting the results (`headline` section).

### Example rule
Here's an example rule that looks at SpiderFoot scan results for data revealing open TCP ports where the banner (the data returned upon connecting to the port) reports a software version. It does so by applying some regular expressions to the content of `TCP_PORT_OPEN_BANNER` data elements, filtering out some false positives and then grouping the results by the banner itself  so that one correlation result is created per banner revealing a version:

```yaml
id: open_port_version
version: 1
meta:
  name: Open TCP port reveals version
  description: >
    A possible software version has been revealed on an open port. Such
    information may reveal the use of old/unpatched software used by
    the target.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: TCP_PORT_OPEN_BANNER
      - method: regex
        field: data
        value: .*[0-9]\.[0-9].*
      - method: regex
        field: data
        value: not .*Mime-Version.*
      - method: regex
        field: data
        value: not .*HTTP/1.*
aggregation:
  field: data
headline: "Software version revealed on open port: {data}"
```

### The outcome
To show this in practice, we can run a simple scan against a target, in this case focusing on performing a port scan:

```
-> # python3.9 ./sf.py -s www.binarypool.com -m sfp_dnsresolve,sfp_portscan_tcp            
2022-04-06 08:14:58,476 [INFO] sflib : Scan [94EB5F0B] for 'www.binarypool.com' initiated.
...
sfp_portscan_tcp    Open TCP Port Banner    SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10
...
2022-04-06 08:15:23,110 [INFO] correlation : New correlation [open_port_version]: Software version revealed on open port: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10
2022-04-06 08:15:23,244 [INFO] sflib : Scan [94EB5F0B] completed.
```
We can see above that a port was found to be open by the `sfp_portscan_tcp` module, and it happens to include a version. The correlation rule `open_port_version` picked this up and reported it. This is also visible in the web interface:

<img src="https://www.spiderfoot.net/wp-content/uploads/2022/04/sf4correlations.png" />

**NOTE:** Rules will only succeed if relevant data exists in your scan results in the first place. In other words, correlation rules analyze scan data, they don't collect data from targets.

### How it works
In short, SpiderFoot translates the YAML rules into a combination queries against the backend database of scan results and Python logic to filter and group the results, creating "correlation results" in the SpiderFoot database. These results can be viewed in the SpiderFot web interface or from the SpiderFoot CLI. You can also query them directly out of the SQLite database if you like (they are in the `tbl_scan_correlation_results` table, and the `tbl_scan_correlation_results_events` table maps the events (data elements) to the correlation result).

### The rules

Each rule exists as a YAML file within the `/correlations` folder in the SpiderFoot installation path. Here you can see a list of rules in 4.0, which we hope to grow over time:

```sh
cert_expired.yaml                    host_only_from_certificatetransparency.yaml  outlier_ipaddress.yaml
cloud_bucket_open.yaml               http_errors.yaml                             outlier_registrar.yaml
cloud_bucket_open_related.yaml       human_name_in_whois.yaml                     outlier_webserver.yaml
data_from_base64.yaml                internal_host.yaml                           remote_desktop_exposed.yaml
data_from_docmeta.yaml               multiple_malicious.yaml                      root_path_needs_auth.yaml
database_exposed.yaml                multiple_malicious_affiliate.yaml            stale_host.yaml
dev_or_test_system.yaml              multiple_malicious_cohost.yaml               strong_affiliate_certs.yaml
dns_zone_transfer_possible.yaml      name_only_from_pasteleak_site.yaml           strong_similardomain_crossref.yaml
egress_ip_from_wikipedia.yaml        open_port_version.yaml                       template.yaml
email_in_multiple_breaches.yaml      outlier_cloud.yaml                           vulnerability_critical.yaml
email_in_whois.yaml                  outlier_country.yaml                         vulnerability_high.yaml
email_only_from_pasteleak_site.yaml  outlier_email.yaml                           vulnerability_mediumlow.yaml
host_only_from_bruteforce.yaml       outlier_hostname.yaml
```
### Rule components

The rules themselves are broken down into the following components:

**Meta**: Describes the rule itself so that humans understand what the rule does and the risk level of any results. This information is used mostly in the web interface and CLI.

**Collections**: A collection represents a set of data pulled from scan results, to be used in later aggregation and analysis stages. Each rule can have multiple collections.

**Aggregations**: An aggregation buckets the collected data into groups for analysis in distinct groups of data elements.

**Analysis**: Analysis performs (you guessed it) analysis on the data to whittle down the data elements to what ultimately gets reported. For example, the analysis stage may look only for cases where the data field is repeated in the data set, indicating it was found multiple times and therefore discarding any only appearing once.

**Headline**: The headline represents the actual correlation title that summarizes what was found. You can think of this as equivalent to a meal name (beef stew), and all the data elements as being the ingredients (beef, tomatoes, onions, etc.).

### Creating a rule

To create your own rule, simply copy the `template.yaml` file in the `correlations` folder to a meaningful name that matches the ID you intend to provide it, e.g. `aws_cloud_usage.yaml` and edit the rule to fit your needs. Save it and re-start SpiderFoot for the rule to be loaded. If there are any syntax errors, SpiderFoot will abort at startup and (hopefully) give you enough information to know where the error is.

The `template.yaml` file is also a good next point of reference to better understand the structure of the rules and how to use them. We also recommend taking a look through the actual rules themselves to see the concepts in practice.

## Rule Reference

**id**: The internal ID for this rule, which needs to match the filename.

**version**: The rule syntax version. This must be `1` for now.

**meta**: This section contains a few important fields used to describe the rule.

  * **name**: A short, human readable name for the rule.
  * **description**: A longer (can be multi-paragraph) description of the rule.
  * **risk**: The risk level represented by this rule's findings. Can be `INFO`, `LOW`, `MEDIUM`, `HIGH`.

**collection**: A correlation rule contains one or more `collect` blocks. Each `collect` block contains one or more `method` blocks telling SpiderFoot what criteria to use for extracting data from the database and how to filter it down. 
  * **collect**: Technically, the first `method` block in each `collect` block is what actually pulls data from the database, and each subsequent `method` refines that dataset down to what you’re seeking. You may have multiple `collect` blocks overall but the rule remains that within each `collect`, the first `method` pulls data from the database and subsequent `method` blocks within the `collect` refine that data.

    *  **method**: Each `method` block tells SpiderFoot how to collect and refine data. Each `collect` must contain at least one `method` block. Valid methods are `exact` for performing an exact match of the chosen `field` to the supplied `value`, or `regex` to perform regular expression matching.

    *  **field**: Each `method` block has a `field` upon which the matching should be performed. Valid fields are `type` (e.g. `INTERNET_NAME`), `module` (e.g. `sfp_whois`) and `data`, which would be the value of the data element (e.g. in case of an `INTERNET_NAME`, the `data` would be the hostname). After the first `method` block, you can also prefix the field with `source.`, `child.` or `entity.` to refer to the fields of the source, children or relevant entities of the collected data, respectively (see `multiple_malicious.yaml` and `data_from_docmeta.yaml` as examples of this approach).

    *  **value**: Here you supply the value or values you wish to match against the field you supplied in `field`. If your `method` was `regex`, this would be a regular expression.

**aggregation**: With all the data elements in their collections, you can now aggregate them into buckets for further analysis or immediately generate results from the rule. While the collection phase is about obtaining the data from the database and filtering down to data of interest, the aggregation phase is about grouping that data in different ways in order to support analysis and/or grouping reported results.

Aggregation simply iterates through the data elements in each collection and places them into groups based on the `field` specified. For instance if you pick the `type` field, you’ll end up with data elements with the same `type` field grouped together. The purpose of this grouping is two-fold: to support the analysis stage, or if you don’t have the analysis stage, it’s how your correlation results will be grouped for the user.
  * **field**: The `field` defines how you'd like your data elements grouped together. Just like the `field` option in `method` blocks above, you may prefix the field with `source.`, `child.` or `entity.` to apply the aggregation on those fields of the data element instead. For example, if you intended to look for multiple occurrences of a hostname, you would specify `data` here as that field, since you want to count the number of times the value of the `data` field appears.

**analysis**
The analysis section applies (you guessed it) some analysis to the aggregated results or collections directly if you didn’t perform any aggregation, and drops candidate results if they fail this stage. Various analysis `method` types exist, and each takes different options, described below.

  * **method**:
      * **threshold**: Drop any collection/aggregation of data elements that do not meet the defined thresholds. You would use this analysis rule when wanting to generate a result only when a data element has appeared more or less than a limit specified, for instance reporting when an email address is reported just once, or more than 100 times.
        * **field**: The field you want to apply the threshold too. As per above, you can use `child.`, `source.` and `entity.` field prefixes here too.
        * **count_unique_only**: By default the threshold is applied to the `field` specified on all data elements, but by setting `count_unique_only` to `true`, you can limit the threshold to only unique values in the `field` specified, so as not to also count duplicates.
        * **minimum**: The minimum number of data elements that must appear within the collection or aggregation.
        * **maximum**: The maximum number of data elements that must appear within the collection or aggregation.
      * **outlier**: Only keep outliers within any collection/aggregation of data elements.
        * **maximum_percent**: The maximum percentage of the overall results that an aggregation can represent. This method requires that you have performed an aggregation on a certain field in order to function. For example, if you aggregate on the `data` field of your collections, and one of those buckets contains less than 10% of the overall volume, it will be reported as an outlier.
        * **noisy_percent**: By default this is `10`, meaning that if the average percentage every bucket is below 10%, don't report outliers since the dataset is anomalous.
      * **first_collection_only**: Only keep data elements that appeared in the first collection but not any others. For example, this is handy for finding cases where data was found from one or several data sources but not others.
        * **field**: The field you want to use for looking up between collections.
      * **match_all_to_first_collection**: Only keep data elements that have matched in some way to the first collection. This requires an aggregation to have been performed, as the field used for aggregation is what will be used for checking for a match.
        * **match_method**: How to match between all collections and the first collection. Options are `contains` (simple wildcard match), `exact` and `subnet` which reports a match if the expected field may contain an IP address that is within the first collection field containing a subnet.

**headline**
After all data elements have been collected, filtered down, aggregated and analyzed, if data elements are remaining, these are what we call "correlation results" -> the results of your correlation rule. These need a "headline" to summarize the findings, which you can define here. To place any value from your data into the headline, you must enclose the field in `{}`, e.g. `{entity.data}`. There are two ways to write a `headline` rule. The typical way is to simply have `headline: titletexthere`, or have it as a block, in which case you can be more granular about how the correlation results are published:

* **text**: The headline text, as described above.
* **publish_collections**: The collection you wish to have associated with the correlation result. This is not often needed, but more in combination with the `match_all_to_first_collection` analysis rule in case your first collection is only used as a reference point and not actually contain any data elements you wish to publish with this correlation result. Take a look at the `egress_ip_from_wikipedia.yaml` rule for an example of this used in practice.

### A note about `child.`, `source.` and `entity.` field prefixes

Every data element pulled in the first `match` rule in a collection will also have any children (data resulting from that data element), the source (the data element that this data element was generated from) and entity (the source, or source of source, etc. that was an entity like IP address, domain, etc.). This enables you to prefix subsequent (and only subsequent!) match block field names with `child.`, `source.` and `entity.` if you wish to match based on those fields. These prefixes, as shown above, can also be used in the `aggregation`, `analysis` and `headline` sections too.

It is vital to note that these prefixes **always** are in reference to the first `match` block within each `collect` block, since every subsequent `match` block is always a refinement of the first `match` block.

This can be complicated, so let's use an example to illustrate. Let's say your scan has found a hostname (a data element type of `INTERNET_NAME`) of `foo`, and it found that within some webpage content (a data element type of `TARGET_WEB_CONTENT`) of "This is some web content: foo", which was from a URL (data element type of `LINKED_URL_INTERNAL`) of "https://bar/page.html", which was from another host named `bar`. Here's the data discovery path:

`bar` [`INTERNET_NAME`] -> `https://bar/page.html` [`LINKED_URL_INTERNAL`] -> `This is some web content: foo` [`TARGET_WEB_CONTENT`] -> `foo` [`INTERNET_NAME`]

If we were to look at `This is some web content: foo` in our rule, here are the `data` and `type` fields you would expect to exist (`module` would also exist but has been left out of this example for brevity):
* `data`: `This is some web content: foo`
* `type`: `TARGET_WEB_CONTENT`
* `source.data`: `https://bar/page.html`
* `source.type`: `LINKED_URL_INTERNAL`
* `child.data`: `foo`
* `child.type`: `INTERNET_NAME`
* `entity.type`: `INTERNET_NAME`
* `entity.data`: `bar`

Notice how the `entity.type` and `entity.data` fields for "This is some web content: foo" is **not** the `LINKED_URL_INTERNAL` data element, but actually the `bar` `INTERNET_NAME` data element. This is because an `INTERNET_NAME` is an entity, but a `LINKED_URL_INTERNAL` is not.

You can look in `spiderfoot/db.py` to see which data types are entities and which are not.


================================================
FILE: correlations/cert_expired.yaml
================================================
id: cert_expired
version: 1
meta:
  name: Expired SSL certificate found
  description: >
    A host was found with an expired SSL certificate. This may
    pose a risk to the security of the service exposed and/or
    cause connecting services to fail due to being unable to
    verify the certificate.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: SSL_CERTIFICATE_EXPIRED
aggregation:
  field: source.data
headline: "Expired SSL certificate found: {source.data}"


================================================
FILE: correlations/cloud_bucket_open.yaml
================================================
id: cloud_bucket_open
version: 1
meta:
  name: Cloud storage bucket open to the Internet
  description: >
    A cloud storage bucket (e.g. S3) referenced from the target
    website has been found to be open to the Internet. Such
    buckets should be restricted so that contents cannot be
    listed, even if needing to be publicly accessible.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: CLOUD_STORAGE_BUCKET
      - method: exact
        field: source.type
        value: LINKED_URL_EXTERNAL
      - method: exact
        field: child.type
        value: CLOUD_STORAGE_BUCKET_OPEN
aggregation:
  field: data
headline: "Cloud storage bucket found open: {data}"


================================================
FILE: correlations/cloud_bucket_open_related.yaml
================================================
id: cloud_bucket_open_related
version: 1
meta:
  name: Possibly related cloud storage bucket open to the Internet
  description: >
    A cloud storage bucket (e.g. S3) potentially related to
    the target has been found to be open to the Internet.

    As the buckets in this case are based on name-matching, verification
    for actual association with the target is necessary.
  risk: LOW
collections:
  - collect:
      - method: exact
        field: type
        value: CLOUD_STORAGE_BUCKET
      - method: exact
        field: source.type
        value: not LINKED_URL_EXTERNAL
      - method: exact
        field: child.type
        value: CLOUD_STORAGE_BUCKET_OPEN
aggregation:
  field: data
headline: "Potentially relevant cloud storage bucket found open: {data}"


================================================
FILE: correlations/data_from_base64.yaml
================================================
id: data_from_base64
version: 1
meta:
  name: Data was found within base64-encoded data
  description: >
    Possibly interesting data was found within base64-encoded data,
    such as software versions, names, email addresses and hostnames.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: BASE64_DATA
      - method: regex
        field: child.data
        value: .*
      - method: exact
        field: child.type
        value: not HASH
aggregation:
  field: child.data
headline: "Interesting data was found within base64-encoded data: '{child.data}'"


================================================
FILE: correlations/data_from_docmeta.yaml
================================================
id: data_from_docmeta
version: 1
meta:
  name: Data was found within document/image meta data
  description: >
    Possibly interesting data was found within document/image meta data,
    such as software versions, names, email addresses and hostnames.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: RAW_FILE_META_DATA
      - method: regex
        field: child.data
        value: .*
      - method: exact
        field: child.type
        value: not HASH
aggregation:
  field: child.data
headline: "Interesting data was found within document meta data: '{child.data}'"


================================================
FILE: correlations/database_exposed.yaml
================================================
id: database_exposed
version: 1
meta:
  name: Database server exposed to the Internet
  description: >
    A database technology (MySQL, Oracle, Postgres, Redis,
    Hadoop, MongoDB, Spark) was found to be accessible over
    the Internet.

    Even if authentication is required such systems should not
    be exposed over the Internet due to the risk of misconfiguration
    or unpatched vulnerabilities.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: TCP_PORT_OPEN
      - method: regex
        field: data
        value:
          # MySQL
          - .*:3306$
          # Oracle
          - .*:1521$
          # PostgreSQL
          - .*:5432$
          # Redis
          - .*:6379$
          - .*:6380$
          # Hadoop
          - .*:50070$
          - .*:50470$
          - .*:50090$
          - .*:500[12]0$
          - .*:50475$
          - .*:50075$
          - .*:8020$
          - .*:9000$
          # Spark
          - .*:7077$
          # MongoDB
          - .*:2701[789]$
aggregation:
  field: data
headline: "Database server exposed to the Internet: {data}"


================================================
FILE: correlations/dev_or_test_system.yaml
================================================
id: dev_or_test_system
version: 1
meta:
  name: A host appearing to be a test or development system was found
  description: >
    A host that has dev, test, staging, internal or uat in its
    name was found. This may indicate a system that is exposed
    over the Internet unintentionally, and/or may be less secure
    than other systems.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: regex
        field: data
        value:
          - .*dev.*
          - .*test.*
          - .*uat.*
          - .*internal.*
          - .*staging.*
aggregation:
  field: data
headline: "Development or internal system found: {data}"


================================================
FILE: correlations/dns_zone_transfer_possible.yaml
================================================
id: dns_zone_transfer_possible
version: 1
meta:
  name: DNS Zone Transfer is possible
  description: >
    It was possible to perform a DNS Zone Transfer with the
    target's name server. Zone transfers can expose a significant
    amount of information about the target network and have no
    real need to be enabled in modern networks.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: module
        value: sfp_dnszonexfer
aggregation:
  field: source.data
headline: "DNS Zone Transfer possible with {source.data}"


================================================
FILE: correlations/egress_ip_from_wikipedia.yaml
================================================
id: egress_ip_from_wikipedia
version: 1
meta:
  name: Wikipedia page edit from target-owned network
  description: >
    A Wikipedia page edit was found to come from an IP address
    within a network owned by the target. That IP address is
    highly likely to be that of a VPN server or office egress
    proxy/gateway.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: NETBLOCK_OWNER
  - collect:
      - method: exact
        field: type
        value: IP_ADDRESS
      - method: exact
        field: child.type
        value: WIKIPEDIA_PAGE_EDIT
aggregation:
  field: data
analysis:
  - method: match_all_to_first_collection
    field: data
    # Could also be 'contains' or 'exact'
    match_method: subnet
headline:
  text: "Wikipedia edit from IP within target-owned network: {data}"
  publish_collections:
    - 1


================================================
FILE: correlations/email_in_multiple_breaches.yaml
================================================
id: email_in_multiple_breaches
version: 1
meta:
  name: >
    An email address was reported to be in multiple breaches
  description: >
    An email address was reported to be in multiple breaches.

    The presence in multiple breaches may indicate that the password
    of the account is particularly weak, or that it was re-used across
    the sites involved in the breaches. Note that some breaches simply
    aggregate other breaches, or may be very old.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: EMAILADDR_COMPROMISED
aggregation:
  field: source.data
analysis:
  - method: threshold
    field: source.data
    minimum: 2
headline: "Email address reported in multiple breaches: {source.data}"


================================================
FILE: correlations/email_in_whois.yaml
================================================
id: email_in_whois
version: 1
meta:
  name: A target-relevant email address was found in Whois data
  description: >
    An email address was found in Whois data that is directly
    related to the target (e.g. same domain). The email found may
    be that of a highly privileged person responsible for
    maintaining the infrastructure of the target.

    Email addresses are increasingly rarely found in Whois data due
    to GDPR.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: EMAILADDR
      - method: regex
        field: source.type
        value: .*WHOIS.*
aggregation:
  field: data
headline: "Email address found in Whois record: {data}"


================================================
FILE: correlations/email_only_from_pasteleak_site.yaml
================================================
id: email_only_from_pasteleak_site
version: 1
meta:
  name: Email address only from paste/leak site
  description: >
    An email address was found mentioned in a paste/leak site but
    nowhere else.

    Since the email address was not found anywhere else, this may indicate
    that the address is in some way special, perhaps not intended to
    be publicly exposed/used or targeted in an attack.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: EMAILADDR
      - method: exact
        field: source.type
        value:
          - LEAKSITE_CONTENT
  - collect:
      - method: exact
        field: type
        value: EMAILADDR
      - method: exact
        field: source.type
        value:
          - not LEAKSITE_CONTENT
aggregation:
  field: data
analysis:
  - method: first_collection_only
    field: data
headline: "Email address found only in paste/leak site: {data}"


================================================
FILE: correlations/host_only_from_bruteforce.yaml
================================================
id: host_only_from_bruteforce
version: 1
meta:
  name: Host only from bruteforcing
  description: >
    A hostname was found only by brute-forcing but nowhere else.

    Since the host was not found anywhere else, this may indicate
    that the host is in some way special, perhaps not intended to
    be publicly exposed/used.
  risk: LOW
collections:
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: exact
        field: module
        value: sfp_dnsbrute
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: exact
        field: module
        value: not sfp_dnsbrute
aggregation:
  field: data
analysis:
  - method: first_collection_only
    field: data
headline: "Host found only through bruteforcing: {data}"


================================================
FILE: correlations/host_only_from_certificatetransparency.yaml
================================================
id: host_only_from_certificatetransparency
version: 1
meta:
  name: Hostname only from certificate transparency
  description: >
    A hostname was found from certificate transparency but
    nowhere else.

    Since the host was not found anywhere else, this may indicate
    that the host is in some way special, perhaps not intended to
    be publicly exposed/used.
  risk: LOW
collections:
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: exact
        field: module
        value:
          - sfp_crt
          - sfp_certspotter
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: exact
        field: module
        value:
          - not sfp_crt
          - not sfp_certspotter
          - not sfp_dnsresolve
aggregation:
  field: data
analysis:
  - method: first_collection_only
    field: data
headline: "Host found only in certificate transparency: {data}"


================================================
FILE: correlations/http_errors.yaml
================================================
id: http_errors
version: 1
meta:
  name: Multiple HTTP errors found
  description: >
    Non-successful HTTP error codes were encountered. 401 and 403
    are not included as these refer to authentication/authorization
    failures.
  risk: LOW
collections:
  - collect:
      - method: exact
        field: type
        value: HTTP_CODE
      - method: regex
        field: data
        value: ^[4-9].*$
      # Leave out authentication/authorization failures
      - method: regex
        field: data
        value: not 40[13]
aggregation:
  field: entity.data
analysis:
  - method: threshold
    minimum: 2
    field: data
headline: "Multiple failure HTTP codes found at {entity.data}"


================================================
FILE: correlations/human_name_in_whois.yaml
================================================
id: human_name_in_whois
version: 1
meta:
  name: A human name was found in Whois data
  description: >
    A human name was found in Whois data. The name found may
    be that of a highly privileged person responsible for
    maintaining the infrastructure of the target.

    Names are increasingly rarely found in Whois data due to
    GDPR.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: HUMAN_NAME
      - method: regex
        field: source.type
        value: .*WHOIS.*
aggregation:
  field: data
headline: "Human name found in Whois record: {data}"


================================================
FILE: correlations/internal_host.yaml
================================================
id: internal_host
version: 1
meta:
  name: A host resolving to unroutable IPs was found
  description: >
    A host that resolves to an IP address on ranges reserved for
    internal use (10.0.0.0/8, etc.) was found to be publicly
    resolvable. This might reveal information about the internal
    infrastructure and workings of the target.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: INTERNAL_IP_ADDRESS
  - collect:
      - method: exact
        field: type
        value: IP_ADDRESS
      - method: regex
        field: data
        value:
          - ^192\\.168\\..*
          - ^10\\..*
      - method: exact
        field: module
        value: sfp_dnsresolve
aggregation:
  field: data
headline: "An internal host was found: {data}"


================================================
FILE: correlations/multiple_malicious.yaml
================================================
id: multiple_malicious
version: 1
meta:
  name: >
    An IP, host, subnet or email address was considered malicious by
    multiple sources
  description: >
    An IP, host, subnet or email address was considered malicious by
    multiple sources.

    Such cases have a high likelihood of being genuinely malicious and
    should be urgently investigated. Even if the entity in question is
    not compromised, it's likely to be blocked across parts of the
    Internet due to its presence in these lists.
  risk: HIGH
collections:
  - collect:
      - method: regex
        field: type
        value:
          - MALICIOUS_*
          - BLACKLIST_*
      # Filter out all subnets
      - method: regex
        field: source.data
        value: not .*/.*
      # Filter out affiliates and Co-hosts
      - method: regex
        field: type
        value:
          - not .*COHOST.*
          - not .*AFFILIATE.*
aggregation:
  field: source.data
analysis:
  - method: threshold
    field: source.data
    minimum: 2
headline: "Entity considered malicious by multiple sources: {source.data}"


================================================
FILE: correlations/multiple_malicious_affiliate.yaml
================================================
id: multiple_malicious_affiliate
version: 1
meta:
  name: >
    An affiliated IP or host was considered malicious by multiple sources
  description: >
    An affiliated IP or host was considered malicious by multiple sources.

    Such cases have a high likelihood of being genuinely malicious and
    should be investigated depending on the nature of the relationship
    between the target and the affiliate. Even if the entity in question is
    not compromised, it's likely to be blocked across parts of the
    Internet due to its presence in these lists and may therefore have
    an impact on the target.
  risk: LOW
collections:
  - collect:
      - method: regex
        field: type
        value:
          - MALICIOUS_*
          - BLACKLIST_*
      # Filter to only affiliated entities
      - method: regex
        field: type
        value: .*AFFILIATE.*
aggregation:
  field: source.data
analysis:
  - method: threshold
    field: source.data
    minimum: 2
headline: "Affiliated entity considered malicious by multiple sources: {source.data}"


================================================
FILE: correlations/multiple_malicious_cohost.yaml
================================================
id: multiple_malicious_cohost
version: 1
meta:
  name: >
    A co-hosted site was considered malicious by multiple sources
  description: >
    A co-hosted site was considered malicious by multiple sources.

    Such cases have a high likelihood of being genuinely malicious and
    should be investigated depending on the nature of the relationship
    between the target and the co-host. Even if the entity in question is
    not compromised, it's likely to be blocked across parts of the
    Internet due to its presence in these lists and may therefore have
    an impact on the target.
  risk: LOW
collections:
  - collect:
      - method: regex
        field: type
        value:
          - MALICIOUS_*
          - BLACKLIST_*
      # Filter to only co-hosted sites
      - method: regex
        field: type
        value: .*COHOST.*
aggregation:
  field: source.data
analysis:
  - method: threshold
    field: source.data
    minimum: 2
headline: "Co-hosted site considered malicious by multiple sources: {source.data}"


================================================
FILE: correlations/name_only_from_pasteleak_site.yaml
================================================
id: name_only_from_pasteleak_site
version: 1
meta:
  name: Human name only from paste/leak site
  description: >
    A human name was found mentioned in a paste/leak site but
    nowhere else.

    Since the name was not found anywhere else, this may indicate
    that the name is in some way special, perhaps not intended to
    be publicly exposed/used or targeted in an attack.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: exact
        field: source.type
        value:
          - LEAKSITE_CONTENT
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
      - method: exact
        field: source.type
        value:
          - not LEAKSITE_CONTENT
aggregation:
  field: data
analysis:
  - method: first_collection_only
    field: data
headline: "Human name found only in paste/leak site: {data}"


================================================
FILE: correlations/open_port_version.yaml
================================================
id: open_port_version
version: 1
meta:
  name: Open TCP port reveals version
  description: >
    A possible software version has been revealed on an open port. Such
    information may reveal the use of old/unpatched software used by
    the target.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: TCP_PORT_OPEN_BANNER
      - method: regex
        field: data
        value: .*[0-9]\.[0-9].*
      - method: regex
        field: data
        value: not .*Mime-Version.*
      - method: regex
        field: data
        value: not .*HTTP/1.*
aggregation:
  field: data
headline: "Software version revealed on open port: {data}"


================================================
FILE: correlations/outlier_cloud.yaml
================================================
id: outlier_cloud
version: 1
meta:
  name: Outlier Cloud provider
  description: >
    A cloud provider that appeared in 10% or less of the
    total providers found. Outliers can often reveal
    entities that are rare and therefore interesting.

    Particularly in the case of cloud providers, an outlier
    may be an indicator of Shadow IT or unmtaintained
    infrastructure.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: PROVIDER_HOSTING
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier cloud provider found: {data}"


================================================
FILE: correlations/outlier_country.yaml
================================================
id: outlier_country
version: 1
meta:
  name: Outlier country
  description: >
    A country that appeared in 10% or less of the total countries
    found. Outliers can often reveal entities that are rare and
    therefore interesting.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: COUNTRY_NAME
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier country found: {data}"


================================================
FILE: correlations/outlier_email.yaml
================================================
id: outlier_email
version: 1
meta:
  name: Outlier email address found
  description: >
    An email address that appeared in 10% or less of the
    total email addresses found. Outliers can often reveal
    entities that are rare and therefore interesting.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: EMAILADDR
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier email address found: {data}"


================================================
FILE: correlations/outlier_hostname.yaml
================================================
id: outlier_hostname
version: 1
meta:
  name: Outlier hostname
  description: >
    A hostname that appeared in 10% or less of the
    total hostnames found. Outliers can often reveal
    entities that are rare and therefore interesting.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: INTERNET_NAME
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier hostname found: {data}"


================================================
FILE: correlations/outlier_ipaddress.yaml
================================================
id: outlier_ipaddress
version: 1
meta:
  name: Outlier IP address
  description: >
    An IP address that appeared in 10% or less of the
    total IP addresses found. Outliers can often reveal
    entities that are rare and therefore interesting.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value:
          - IP_ADDRESS
          - IPV6_ADDRESS
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier IP address found: {data}"


================================================
FILE: correlations/outlier_registrar.yaml
================================================
id: outlier_registrar
version: 1
meta:
  name: Outlier registrar
  description: >
    A registrar that appeared in 10% or less of the total registrars
    found. Outliers can often reveal entities that are rare and
    therefore interesting.

    Particularly in the case of registrars, an outlier may be an
    indicator of Shadow IT or unmtaintained infrastructure.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: DOMAIN_REGISTRAR
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier registrar found: {data}"


================================================
FILE: correlations/outlier_webserver.yaml
================================================
id: outlier_webserver
version: 1
meta:
  name: Outlier web server
  description: >
    A web server that appeared in 10% or less of the
    total web servers found. Outliers can often reveal
    entities that are rare and therefore interesting.

    Particularly in the case of web servers, an outlier
    may be an indicator of Shadow IT or unmtaintained
    infrastructure.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value: WEBSERVER_BANNER
aggregation:
  field: data
analysis:
  - method: outlier
    maximum_percent: 10
headline: "Outlier web server found: {data}"


================================================
FILE: correlations/remote_desktop_exposed.yaml
================================================
id: remote_desktop_exposed
version: 1
meta:
  name: Remote desktop technology found exposed to the Internet
  description: >
    A remote desktop technology (RDP, VNC, NoMachine)
    was found to be accessible over the Internet.

    Even if authentication is required such systems should not
    be exposed over the Internet due to the risk of misconfiguration
    or unpatched vulnerabilities.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: TCP_PORT_OPEN
      - method: regex
        field: data
        value:
          - .*:5900$
          - .*:3389$
          - .*:4000$
aggregation:
  field: source.data
headline: "Remote desktop exposed to the Internet: {source.data}"


================================================
FILE: correlations/root_path_needs_auth.yaml
================================================
id: root_path_needs_auth
version: 1
meta:
  name: Website root path needs authentication
  description: >
    The base path of a server needs authentication, indicating the
    server is likely sensitive or important.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: type
        value: HTTP_CODE
      - method: regex
        field: data
        value: 40[31]
      # The source might be a host or URL
      - method: regex
        field: source.data
        value:
          - ^https?://[a-zA-Z0-9\.\-]+/?#?$
          - ^[a-zA-Z0-9\.\-]+$
aggregation:
  field: source.data
headline: "Base URL requires authentication: {source.data}"


================================================
FILE: correlations/stale_host.yaml
================================================
id: stale_host
version: 1
meta:
  name: Stale host found
  description: >
    A host appears to be stale based upon various indicators such
    as unsuccessful HTTP codes, expired SSL certificates, error
    messages, vulnerabilities and junk files found. Such hosts
    may be unmaintained, exposing the target to security risks.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: SSL_CERTIFICATE_EXPIRED
  - collect:
      - method: exact
        field: type
        value: HTTP_CODE
      - method: regex
        field: data
        value: not ^[2-3].*$
      - method: regex
        field: data
        value: not 40[13]
  - collect:
      - method: exact
        field: type
        value: ERROR_MESSAGE
  - collect:
      - method: exact
        field: type
        value: JUNK_FILE
  - collect:
      - method: regex
        field: type
        value: VULNERABILITY_.*
aggregation:
  field: entity.data
analysis:
  - method: threshold
    field: type
    # Avoid multiple of the same type triggering. This means
    # a minimum of 3 of different types must appear in one
    # bucket.
    count_unique_only: true
    minimum: 3
headline: "Potentially stale/unmaintained host: {entity.data}"


================================================
FILE: correlations/strong_affiliate_certs.yaml
================================================
id: strong_affiliate_certs
version: 1
meta:
  name: Affiliated host/domain with strong relationship to the target
  description: >
    A host or domain was found to be referenced multiple times from
    SSL certificates covering multiple target hosts.

    Strong affiliates indicate potential targets that should be
    included in the scope of scanning to ensure more complete coverage.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: module
        value:
          - sfp_sslcert
          - sfp_crt
          - sfp_certspotter
      - method: exact
        field: source.type
        value:
          - INTERNET_NAME
          - DOMAIN_NAME
      - method: exact
        field: type
        value:
          - AFFILIATE_INTERNET_NAME
          - AFFILIATE_DOMAIN_NAME
          - CO_HOSTED_SITE
          - CO_HOSTED_SITE_DOMAIN
aggregation:
  field: data
analysis:
  - method: threshold
    field: source.data
    count_unique_only: true
    minimum: 2
headline: "Affiliate with strong target relationship: {data}"


================================================
FILE: correlations/strong_similardomain_crossref.yaml
================================================
id: strong_similardomain_crossref
version: 1
meta:
  name: Similar domain with strong relationship to the target
  description: >
    A similar domain was found to be referenced by the target, and
    references back, indicating a strong relationship.

    Strong affiliates indicate potential targets that should be
    included in the scope of scanning to ensure more complete coverage.
  risk: INFO
collections:
  - collect:
      - method: exact
        field: module
        value: sfp_crossref
      - method: exact
        field: type
        value: AFFILIATE_INTERNET_NAME
      - method: exact
        field: source.type
        value: SIMILARDOMAIN
aggregation:
  field: data
headline: "Similar domain with strong target relationship: {data}"


================================================
FILE: correlations/template.yaml
================================================
# Set the ID for the rule. Ensure it matches the filename (without the .yaml
# extension) and has no spaces or other special characters.
id: set_a_meaningful_id_here

# Use version 1 for now.
version: 1

# The meta section sets meta attributes about the rule.
meta:

  # The human-readable name for the rule
  name: This is a briefly descriptive name.

  # A longer description for the rule
  description: >
      This is a more detailed description about the rule and ideally
      includes some rationale explaining the risk posed, or other
      relevant information that helps the user better understand the
      value of the rule results.

      You can have multiple paragraphs here too.

      For this example rule, our goal is to find all hosts that
      match "foo" or "bar", creating a correlation result when such a
      host is found more than once.

  # The risk the results of this rule posed. They can be one of:
  # - HIGH (reserved for genuine cases requiring immediate action)
  # - MEDIUM (potential high risk, needs deeper examination)
  # - LOW (potential risk, but probably low risk or false positive)
  # - INFO (no risk posed but potential interesting information)
  risk: MEDIUM

# Define the collections to perform here. Refer to the README.md
# in the correlations folder for more details.
collections:

  # Each 'collect' block represents a collection of data from
  # the SpiderFoot database. You need at least one 'collect'
  # block for the rule to actually do something.
  - collect:
      # Each 'collect' block may contain multiple blocks
      # for collecting and analyzing data. The first pulls
      # data from the SpiderFoot database, and subsequent
      # blocks further refine that data down to what you are
      # interested in. You need at least one for the 'collect'
      # block to have data.
      #
      # For example, this rule will extract all data elements
      # that exactly match the INTERNET_NAME type.
      - method: exact
        field: type
        value: INTERNET_NAME
      # This next rule will filter out all the INTERNET_NAME
      # results where data doesn't match any of the regular
      # expressions provided.
      - method: regex
        field: data
        value:
          - .*foo.*
          - .*bar.*
      # What we are now left with in this collection are all
      # INTERNET_NAME elements with data matching either .*foo.*
      # or .*bar.*

# With the data from your one or more collections, you can
# now use 'aggregation' to define how they should be grouped
# (if at all) for analysis at the next stage (also optional).
aggregation:
  # Each data element will be placed into a bucket according
  # to its data field, which is the hostname since we have
  # INTERNET_NAME data elements.
  field: data

# Analysis is an optional step to perform analysis on the
# (optionally aggegated) data gathered to apply some criteria
# determining whether a correlation creates results or not.
analysis:
  # Here we want to only generate a correlation result when
  # the value of the data element's data field (the hostname
  # in this case) appears at least two times.
  - method: threshold
    minimum: 2
    field: data

# With the collection, aggegation and analysis performed,
# we can now generate the correlation result with a title
# that represents something meaningful to the user.
headline: "A foo or bar host was found more than once: {data}"


================================================
FILE: correlations/vulnerability_critical.yaml
================================================
id: vulnerability_critical
version: 1
meta:
  name: At least one CRITICAL-rated vulnerability was found
  description: >
    A vulnerability rated as CRITICAL was found on a host.

    Such vulnerabilities are typically easily exploitable and should
    be urgently patched.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: VULNERABILITY_CVE_CRITICAL
aggregation:
  field: entity.data
headline: "Critical-rated vulnerability found on {entity.data}"


================================================
FILE: correlations/vulnerability_high.yaml
================================================
id: vulnerability_high
version: 1
meta:
  name: At least one HIGH-rated vulnerability was found
  description: >
    A vulnerability rated as HIGH was found on a host.

    Such vulnerabilities are typically easily exploitable and should
    be urgently patched.
  risk: HIGH
collections:
  - collect:
      - method: exact
        field: type
        value: VULNERABILITY_CVE_HIGH
aggregation:
  field: entity.data
headline: "High-rated vulnerability found on {entity.data}"


================================================
FILE: correlations/vulnerability_mediumlow.yaml
================================================
id: vulnerability_mediumlow
version: 1
meta:
  name: Multiple MEDIUM or LOW-rated vulnerabilities were found
  description: >
    Multiple vulnerabilities rated as MEDIUM or LOW were found on a host.

    Such vulnerabilities pose a lower risk to the target, however in
    aggregate may be an indication that the host is not well maintained.
  risk: MEDIUM
collections:
  - collect:
      - method: exact
        field: type
        value:
          - VULNERABILITY_CVE_MEDIUM
          - VULNERABILITY_CVE_LOW
          - VULNERABILITY_GENERAL
aggregation:
  field: entity.data
analysis:
  - method: threshold
    field: entity.data
    minimum: 2
headline: "Multiple medium/low vulnerabilities found on {entity.data}"


================================================
FILE: docker-compose-dev.yml
================================================
version: "3"

services:
  spiderfoot:
    volumes:
      - .:/home/spiderfoot


================================================
FILE: docker-compose-full.yml
================================================
version: "3"

services:
  spiderfoot:
    build:
      context: ./
      dockerfile: ./Dockerfile.full


================================================
FILE: docker-compose.yml
================================================
version: "3"

# Basic usage:
#     $ docker-compose up
#
# Dev environment (code directory mapped into container):
#     $ docker-compose -f docker-compose.yml -f docker-compose-dev.yml up
#
# Full image (all CLI tools installed):
#     $ docker-compose -f docker-compose.yml -f docker-compose-full.yml up
#
# Spiderfoot data resides in a Docker volume
#
#     $ ls -lh /var/lib/docker/volumes/spiderfoot_spiderfoot-data/_data
#       total 104K
#       drwxr-xr-x 2 user user 4.0K Sep 22 09:51 cache
#       -rw-r--r-- 1 user user 100K Sep 22 15:19 spiderfoot.db

services:
  spiderfoot:
    build:
      context: ./
    volumes:
      - spiderfoot-data:/var/lib/spiderfoot
    image: spiderfoot
    container_name: spiderfoot
    ports:
      - "5001:5001"
    restart: unless-stopped

volumes:
  spiderfoot-data:


================================================
FILE: docs/Makefile
================================================
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = .
BUILDDIR      = _build

# Put it first so that "make" without argument is like "make help".
help:
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)


================================================
FILE: docs/conf.py
================================================
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, '/root/Desktop/spiderfoot/spiderfoot')


# -- Project information -----------------------------------------------------

project = 'SpiderFoot'
copyright = '2012, Steve Micallef'
author = 'Steve Micallef'


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.napoleon',
    'sphinx.ext.viewcode',
    'sphinx.ext.todo',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']


# -- Extension configuration -------------------------------------------------

# -- Options for todo extension ----------------------------------------------

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True


================================================
FILE: docs/index.rst
================================================
.. spiderfoot documentation master file, created by
   sphinx-quickstart on Sat Jun 26 01:55:34 2021.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to spiderfoot's documentation!
======================================

.. toctree::
   :maxdepth: 4
   :caption: Contents:

   spiderfoot


Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`


================================================
FILE: docs/make.bat
================================================
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
	set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
	echo.
	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
	echo.installed, then set the SPHINXBUILD environment variable to point
	echo.to the full path of the 'sphinx-build' executable. Alternatively you
	echo.may add the Sphinx directory to PATH.
	echo.
	echo.If you don't have Sphinx installed, grab it from
	echo.http://sphinx-doc.org/
	exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd


================================================
FILE: docs/spiderfoot.rst
================================================
spiderfoot package
==================

Submodules
----------

spiderfoot.db module
--------------------

.. automodule:: spiderfoot.db
   :members:
   :undoc-members:
   :show-inheritance:

spiderfoot.event module
-----------------------

.. automodule:: spiderfoot.event
   :members:
   :undoc-members:
   :show-inheritance:

spiderfoot.helpers module
-------------------------

.. automodule:: spiderfoot.helpers
   :members:
   :undoc-members:
   :show-inheritance:

spiderfoot.plugin module
------------------------

.. automodule:: spiderfoot.plugin
   :members:
   :undoc-members:
   :show-inheritance:

spiderfoot.target module
------------------------

.. automodule:: spiderfoot.target
   :members:
   :undoc-members:
   :show-inheritance:

Module contents
---------------

.. automodule:: spiderfoot
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: generate-certificate
================================================
#!/bin/sh
if ! command -v openssl >/dev/null 2>&1 ; then
  echo "Error: Could not find openssl in \$PATH: $PATH"
  exit 1
fi

if test -f spiderfoot.key; then
  echo "Error: spiderfoot.key already exists"
  exit 1
fi

if test -f spiderfoot.crt; then
  echo "Error: spiderfoot.crt already exists"
  exit 1
fi

openssl req -new -newkey rsa:4096 -sha256 -x509 -days 365 -nodes -out spiderfoot.crt -keyout spiderfoot.key -subj "/CN=localhost"

chmod 600 spiderfoot.crt
chmod 600 spiderfoot.key


================================================
FILE: modules/__init__.py
================================================


================================================
FILE: modules/sfp__stor_db.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:         sfp_stor_db
# Purpose:      SpiderFoot plug-in for storing events to the local SpiderFoot
#               SQLite database.
#
# Author:      Steve Micallef <steve@binarypool.com>
#
# Created:     14/05/2012
# Copyright:   (c) Steve Micallef 2012
# Licence:     MIT
# -------------------------------------------------------------------------------

from spiderfoot import SpiderFootPlugin


class sfp__stor_db(SpiderFootPlugin):

    meta = {
        'name': "Storage",
        'summary': "Stores scan results into the back-end SpiderFoot database. You will need this."
    }

    _priority = 0

    # Default options
    opts = {
        'maxstorage': 1024,  # max bytes for any piece of info stored (0 = unlimited)
        '_store': True
    }

    # Option descriptions
    optdescs = {
        'maxstorage': "Maximum bytes to store for any piece of information retrieved (0 = unlimited.)"
    }

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    # What events is this module interested in for input
    # Because this is a storage plugin, we are interested in everything so we
    # can store all events for later analysis.
    def watchedEvents(self):
        return ["*"]

    # Handle events sent to this module
    def handleEvent(self, sfEvent):
        if not self.opts['_store']:
            return

        if self.opts['maxstorage'] != 0 and len(sfEvent.data) > self.opts['maxstorage']:
            self.debug("Storing an event: " + sfEvent.eventType)
            self.__sfdb__.scanEventStore(self.getScanId(), sfEvent, self.opts['maxstorage'])
            return

        self.debug("Storing an event: " + sfEvent.eventType)
        self.__sfdb__.scanEventStore(self.getScanId(), sfEvent)

# End of sfp__stor_db class


================================================
FILE: modules/sfp__stor_stdout.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:         sfp_stor_stdout
# Purpose:      SpiderFoot plug-in for dumping events to standard output.
#
# Author:      Steve Micallef <steve@binarypool.com>
#
# Created:     22/10/2018
# Copyright:   (c) Steve Micallef 2018
# Licence:     MIT
# -------------------------------------------------------------------------------

import json

from spiderfoot import SpiderFootPlugin


class sfp__stor_stdout(SpiderFootPlugin):

    meta = {
        'name': "Command-line output",
        'summary': "Dumps output to standard out. Used for when a SpiderFoot scan is run via the command-line."
    }

    _priority = 0
    firstEvent = True

    # Default options
    opts = {
        "_format": "tab",  # tab, csv, json
        "_requested": [],
        "_showonlyrequested": False,
        "_stripnewline": False,
        "_showsource": False,
        "_csvdelim": ",",
        "_maxlength": 0,
        "_eventtypes": dict()
    }

    # Option descriptions
    optdescs = {
    }

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    # What events is this module interested in for input
    # Because this is a storage plugin, we are interested in everything so we
    # can store all events for later analysis.
    def watchedEvents(self):
        return ["*"]

    def output(self, event):
        d = self.opts['_csvdelim']
        if type(event.data) in [list, dict]:
            data = str(event.data)
        else:
            data = event.data

        if type(data) != str:
            data = str(event.data)

        if type(event.sourceEvent.data) in [list, dict]:
            srcdata = str(event.sourceEvent.data)
        else:
            srcdata = event.sourceEvent.data

        if type(srcdata) != str:
            srcdata = str(event.sourceEvent.data)

        if self.opts['_stripnewline']:
            data = data.replace("\n", " ").replace("\r", "")
            srcdata = srcdata.replace("\n", " ").replace("\r", "")

        if "<SFURL>" in data:
            data = data.replace("<SFURL>", "").replace("</SFURL>", "")
        if "<SFURL>" in srcdata:
            srcdata = srcdata.replace("<SFURL>", "").replace("</SFURL>", "")

        if self.opts['_maxlength'] > 0:
            data = data[0:self.opts['_maxlength']]
            srcdata = srcdata[0:self.opts['_maxlength']]

        if self.opts['_format'] == "tab":
            event_type = self.opts['_eventtypes'][event.eventType]
            if self.opts['_showsource']:
                print(f"{event.module.ljust(30)}\t{event_type.ljust(45)}\t{srcdata}\t{data}")
            else:
                print(f"{event.module.ljust(30)}\t{event_type.ljust(45)}\t{data}")

        if self.opts['_format'] == "csv":
            print((event.module + d + self.opts['_eventtypes'][event.eventType] + d + srcdata + d + data))

        if self.opts['_format'] == "json":
            d = event.asDict()
            d['type'] = self.opts['_eventtypes'][event.eventType]
            if self.firstEvent:
                self.firstEvent = False
            else:
                print(",")
            print(json.dumps(d), end='')

    # Handle events sent to this module
    def handleEvent(self, sfEvent):
        if sfEvent.eventType == "ROOT":
            return

        if self.opts['_showonlyrequested']:
            if sfEvent.eventType in self.opts['_requested']:
                self.output(sfEvent)
        else:
            self.output(sfEvent)

# End of sfp__stor_stdout class


================================================
FILE: modules/sfp_abstractapi.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:        sfp_abstractapi
# Purpose:     Search AbstractAPI for domain, phone and IP address information.
#
# Author:      Krishnasis Mandal <krishnasis@hotmail.com>
#
# Created:     29/07/2021
# Copyright:   (c) Steve Micallef
# Licence:     MIT
# -------------------------------------------------------------------------------

import json
import time
import urllib

from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_abstractapi(SpiderFootPlugin):

    meta = {
        'name': "AbstractAPI",
        'summary': "Look up domain, phone and IP address information from AbstractAPI.",
        'flags': ["apikey"],
        'useCases': ["Passive", "Footprint", "Investigate"],
        'categories': ["Search Engines"],
        'dataSource': {
            'website': "https://app.abstractapi.com/",
            'model': "FREE_NOAUTH_LIMITED",
            'references': [
                "https://app.abstractapi.com/",
            ],
            'apiKeyInstructions': [
                "Visit https://app.abstractapi.com/users/signup",
                "Register a free account",
                "Visit https://app.abstractapi.com/api/",
                "Visit each API page and click on 'Try it out'",
                "Your API Key will be listed under 'This is your private API key, specific to this API.'",
            ],
            'favIcon': "https://app.abstractapi.com/favicon.ico",
            'logo': "https://app.abstractapi.com/logo192.png",
            'description': "Abstract provides powerful APIs to help you enrich any user experience or automate any workflow."
        }
    }

    opts = {
        "companyenrichment_api_key": "",
        "phonevalidation_api_key": "",
        "ipgeolocation_api_key": "",
    }

    optdescs = {
        "companyenrichment_api_key": "AbstractAPI Company Enrichment API key.",
        "phonevalidation_api_key": "AbstractAPI Phone Validation API key.",
        "ipgeolocation_api_key": "AbstractAPI IP Geolocation API key.",
    }

    results = None
    errorState = False

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc
        self.errorState = False
        self.results = self.tempStorage()

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    def watchedEvents(self):
        return ["DOMAIN_NAME", "PHONE_NUMBER", "IP_ADDRESS", "IPV6_ADDRESS"]

    def producedEvents(self):
        return ["COMPANY_NAME", "SOCIAL_MEDIA", "GEOINFO", "PHYSICAL_COORDINATES", "PROVIDER_TELCO", "RAW_RIR_DATA"]

    def parseApiResponse(self, res: dict):
        if not res:
            self.error("No response from Abstract API.")
            return None

        # Rate limited to one request per second
        if res['code'] == '429':
            self.error("You are being rate-limited by AbstractAPI.")
            return None

        if res['code'] == '401':
            self.error("Unauthorized. Invalid AbstractAPI API key.")
            self.errorState = True
            return None

        if res['code'] == '422':
            self.error("Usage quota reached. Insufficient API credit.")
            self.errorState = True
            return None

        if res['code'] == '500' or res['code'] == '502' or res['code'] == '503':
            self.error("Abstract API service is unavailable")
            self.errorState = True
            return None

        if res['code'] == '204':
            self.debug("No response data for target")
            return None

        if res['code'] != '200':
            self.error(f"Unexpected reply from AbstractAPI: {res['code']}")
            return None

        if res['content'] is None:
            return None

        try:
            return json.loads(res['content'])
        except Exception as e:
            self.debug(f"Error processing JSON response: {e}")

        return None

    def queryCompanyEnrichment(self, qry):
        """Enrich domain with company information.

        Args:
            qry (str): domain name

        Returns:
            dict: company information
        """

        api_key = self.opts['companyenrichment_api_key']
        if not api_key:
            return None

        params = urllib.parse.urlencode({
            'api_key': api_key,
            'domain': qry.encode('raw_unicode_escape').decode("ascii", errors='replace'),
        })

        res = self.sf.fetchUrl(
            f"https://companyenrichment.abstractapi.com/v1/?{params}",
            useragent=self.opts['_useragent']
        )

        time.sleep(1)

        if not res:
            self.debug("No response from AbstractAPI Company Enrichment API endpoint")
            return None

        return self.parseApiResponse(res)

    def queryPhoneValidation(self, qry):
        """Verify phone number and enrich with carrier and location information.

        Args:
            qry (str): phone number

        Returns:
            dict: phone number information
        """

        api_key = self.opts['phonevalidation_api_key']
        if not api_key:
            return None

        params = urllib.parse.urlencode({
            'api_key': api_key,
            'phone': qry.encode('raw_unicode_escape').decode("ascii", errors='replace'),
        })

        res = self.sf.fetchUrl(
            f"https://phonevalidation.abstractapi.com/v1/?{params}",
            useragent=self.opts['_useragent']
        )

        time.sleep(1)

        if not res:
            self.debug("No response from AbstractAPI Phone Validation API endpoint")
            return None

        return self.parseApiResponse(res)

    def queryIpGeolocation(self, qry):
        """Enrich IP address with geolocation information.

        Args:
            qry (str): IPv4 address

        Returns:
            dict: location information
        """

        api_key = self.opts['ipgeolocation_api_key']
        if not api_key:
            return None

        params = urllib.parse.urlencode({
            'api_key': api_key,
            'ip_address': qry.encode('raw_unicode_escape').decode("ascii", errors='replace'),
        })

        res = self.sf.fetchUrl(
            f"https://ipgeolocation.abstractapi.com/v1/?{params}",
            useragent=self.opts['_useragent']
        )

        time.sleep(1)

        if not res:
            self.debug("No response from AbstractAPI Phone Validation API endpoint")
            return None

        return self.parseApiResponse(res)

    def handleEvent(self, event):
        eventName = event.eventType
        srcModuleName = event.module
        eventData = event.data

        self.debug(f"Received event, {eventName}, from {srcModuleName}")

        if eventData in self.results:
            self.debug(f"Skipping {eventData}, already checked.")
            return

        self.results[eventData] = True

        if self.opts["companyenrichment_api_key"] == "" and self.opts["phonevalidation_api_key"] == "" and self.opts["ipgeolocation_api_key"] == "":
            self.error(
                f"You enabled {self.__class__.__name__} but did not set any API keys!"
            )
            self.errorState = True
            return

        if eventName not in self.watchedEvents():
            return

        if eventName == "DOMAIN_NAME":
            if self.opts["companyenrichment_api_key"] == "":
                self.info(
                    f"No API key set for Company Enrichment API endpoint. Ignoring {eventData}"
                )
                return

            data = self.queryCompanyEnrichment(eventData)

            if not data:
                return

            name = data.get('name')
            if not name:
                return

            if name == 'To Be Confirmed':
                return

            e = SpiderFootEvent("RAW_RIR_DATA", str(data), self.__name__, event)
            self.notifyListeners(e)

            e = SpiderFootEvent("COMPANY_NAME", name, self.__name__, event)
            self.notifyListeners(e)

            linkedin_url = data.get('linkedin_url')
            if linkedin_url:
                if linkedin_url.startswith('linkedin.com'):
                    linkedin_url = f"https://{linkedin_url}"
                e = SpiderFootEvent("SOCIAL_MEDIA", f"LinkedIn (Company): <SFURL>{linkedin_url}</SFURL>", self.__name__, event)
                self.notifyListeners(e)

            locality = data.get('locality')
            country = data.get('country')
            geoinfo = ', '.join(
                filter(None, [locality, country])
            )

            if geoinfo:
                e = SpiderFootEvent("GEOINFO", geoinfo, self.__name__, event)
                self.notifyListeners(e)

        elif eventName == "PHONE_NUMBER":
            if self.opts["phonevalidation_api_key"] == "":
                self.info(
                    f"No API key set for Phone Validation API endpoint. Ignoring {eventData}"
                )
                return

            data = self.queryPhoneValidation(eventData)

            if not data:
                return

            valid = data.get('valid')
            if not valid:
                return

            e = SpiderFootEvent("RAW_RIR_DATA", str(data), self.__name__, event)
            self.notifyListeners(e)

            carrier = data.get('carrier')
            if carrier:
                e = SpiderFootEvent("PROVIDER_TELCO", carrier, self.__name__, event)
                self.notifyListeners(e)

            location = data.get('location')
            country = data.get('country')
            country_name = None
            if country:
                country_name = country.get('name')

            geoinfo = ', '.join(
                filter(None, [location, country_name])
            )

            if geoinfo:
                e = SpiderFootEvent("GEOINFO", geoinfo, self.__name__, event)
                self.notifyListeners(e)

        elif eventName in ['IP_ADDRESS', 'IPV6_ADDRESS']:
            if self.opts["ipgeolocation_api_key"] == "":
                self.info(
                    f"No API key set for IP Geolocation API endpoint. Ignoring {eventData}"
                )
                return

            data = self.queryIpGeolocation(eventData)

            if not data:
                return

            e = SpiderFootEvent("RAW_RIR_DATA", str(data), self.__name__, event)
            self.notifyListeners(e)

            geoinfo = ', '.join(
                [
                    _f for _f in [
                        data.get('city'),
                        data.get('region'),
                        data.get('postal_code'),
                        data.get('country'),
                        data.get('continent'),
                    ] if _f
                ]
            )

            if geoinfo:
                e = SpiderFootEvent("GEOINFO", geoinfo, self.__name__, event)
                self.notifyListeners(e)

            latitude = data.get('latitude')
            longitude = data.get('longitude')
            if latitude and longitude:
                e = SpiderFootEvent("PHYSICAL_COORDINATES", f"{latitude}, {longitude}", self.__name__, event)
                self.notifyListeners(e)

# End of sfp_abstractapi class


================================================
FILE: modules/sfp_abusech.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:        sfp_abusech
# Purpose:     Check if a host/domain, IP address or netblock is malicious according
#              to Abuse.ch.
#
# Author:       steve@binarypool.com
#
# Created:     14/12/2013
# Copyright:   (c) Steve Micallef, 2013
# Licence:     MIT
# -------------------------------------------------------------------------------

from netaddr import IPAddress, IPNetwork

from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_abusech(SpiderFootPlugin):

    meta = {
        'name': "abuse.ch",
        'summary': "Check if a host/domain, IP address or netblock is malicious according to Abuse.ch.",
        'flags': [],
        'useCases': ["Passive", "Investigate"],
        'categories': ["Reputation Systems"],
        'dataSource': {
            'website': "https://www.abuse.ch",
            'model': "FREE_AUTH_UNLIMITED",
            'references': [
                "https://feodotracker.abuse.ch/",
                "https://sslbl.abuse.ch/",
                "https://urlhaus.abuse.ch/",
            ],
            'apiKeyInstructions': [
                "Visit https://bazaar.abuse.ch/api#api_key",
                "Login using a Twitter Account",
                "Navigate to 'Account Settings'",
                "The API key is listed under 'Your API Key'",
                "Visit https://urlhaus.abuse.ch/api/",
                "Login using a Twitter Account at https://urlhaus.abuse.ch/login/",
                "Navigate to https://urlhaus.abuse.ch/api/#account",
                "The API Key is listed under 'API-Key'"
            ],
            'favIcon': "https://abuse.ch/favicon.ico",
            'logo': "https://abuse.ch/images/abusech.svg",
            'description': "abuse.ch is operated by a random swiss guy fighting malware for non-profit, "
            "running a couple of projects helping internet service providers and "
            "network operators protecting their infrastructure from malware.\n"
            "IT-Security researchers, vendors and law enforcement agencies rely on data from abuse.ch,"
            "trying to make the internet a safer place.",
        }
    }

    # Default options
    opts = {
        'abusefeodoip': True,
        'abusesslblip': True,
        'abuseurlhaus': True,
        'checkaffiliates': True,
        'checkcohosts': True,
        'cacheperiod': 18,
        'checknetblocks': True,
        'checksubnets': True
    }

    # Option descriptions
    optdescs = {
        'abusefeodoip': "Enable abuse.ch Feodo IP check?",
        'abusesslblip': "Enable abuse.ch SSL Backlist IP check?",
        'abuseurlhaus': "Enable abuse.ch URLhaus check?",
        'checkaffiliates': "Apply checks to affiliates?",
        'checkcohosts': "Apply checks to sites found to be co-hosted on the target's IP?",
        'cacheperiod': "Hours to cache list data before re-fetching.",
        'checknetblocks': "Report if any malicious IPs are found within owned netblocks?",
        'checksubnets': "Check if any malicious IPs are found within the same subnet of the target?"
    }

    results = None
    errorState = False

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc
        self.results = self.tempStorage()
        self.errorState = False

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    # What events is this module interested in for input
    def watchedEvents(self):
        return [
            "INTERNET_NAME",
            "IP_ADDRESS",
            "NETBLOCK_MEMBER",
            "AFFILIATE_INTERNET_NAME",
            "AFFILIATE_IPADDR",
            "CO_HOSTED_SITE",
            "NETBLOCK_OWNER"
        ]

    # What events this module produces
    def producedEvents(self):
        return [
            "MALICIOUS_IPADDR",
            "MALICIOUS_INTERNET_NAME",
            "MALICIOUS_AFFILIATE_IPADDR",
            "MALICIOUS_AFFILIATE_INTERNET_NAME",
            "MALICIOUS_SUBNET",
            "MALICIOUS_COHOST",
            "MALICIOUS_NETBLOCK"
        ]

    def queryFeodoTrackerBlacklist(self, target, targetType):
        blacklist = self.retrieveFeodoTrackerBlacklist()

        if not blacklist:
            return False

        if targetType == "ip":
            if target in blacklist:
                self.debug(f"IP address {target} found in Abuse.ch Feodo Tracker.")
                return True
        elif targetType == "netblock":
            netblock = IPNetwork(target)
            for ip in blacklist:
                if IPAddress(ip) in netblock:
                    self.debug(f"IP address {ip} found within netblock/subnet {target} in Abuse.ch Feodo Tracker.")
                    return True

        return False

    def retrieveFeodoTrackerBlacklist(self):
        blacklist = self.sf.cacheGet('abusech_feodo', 24)

        if blacklist is not None:
            return self.parseFeodoTrackerBlacklist(blacklist)

        res = self.sf.fetchUrl(
            "https://feodotracker.abuse.ch/downloads/ipblocklist.txt",
            timeout=self.opts['_fetchtimeout'],
            useragent=self.opts['_useragent'],
        )

        if res['code'] != "200":
            self.error(f"Unexpected HTTP response code {res['code']} from Abuse.ch Abuse.ch Feodo Tracker.")
            self.errorState = True
            return None

        if res['content'] is None:
            self.error("Received no content from Abuse.ch Feodo Tracker")
            self.errorState = True
            return None

        self.sf.cachePut("abusech_feodo", res['content'])

        return self.parseFeodoTrackerBlacklist(res['content'])

    def parseFeodoTrackerBlacklist(self, blacklist):
        """Parse plaintext blacklist

        Args:
            blacklist (str): plaintext blacklist from Abuse.ch Feodo Tracker

        Returns:
            list: list of blacklisted IP addresses
        """
        ips = list()

        if not blacklist:
            return ips

        for ip in blacklist.split('\n'):
            ip = ip.strip()
            if not ip:
                continue
            if ip.startswith('#'):
                continue
            if not self.sf.validIP(ip):
                continue
            ips.append(ip)

        return ips

    def querySslBlacklist(self, target, targetType):
        blacklist = self.retrieveSslBlacklist()

        if not blacklist:
            return False

        if targetType == "ip":
            if target in blacklist:
                self.debug(f"IP address {target} found in Abuse.ch SSL Blacklist.")
                return True
        elif targetType == "netblock":
            netblock = IPNetwork(target)
            for ip in blacklist:
                if IPAddress(ip) in netblock:
                    self.debug(f"IP address {ip} found within netblock/subnet {target} in Abuse.ch SSL Blacklist.")
                    return True

        return False

    def retrieveSslBlacklist(self):
        blacklist = self.sf.cacheGet('abusech_ssl', 24)

        if blacklist is not None:
            return self.parseSslBlacklist(blacklist)

        res = self.sf.fetchUrl(
            "https://sslbl.abuse.ch/blacklist/sslipblacklist.csv",
            timeout=self.opts['_fetchtimeout'],
            useragent=self.opts['_useragent'],
        )

        if res['code'] != "200":
            self.error(f"Unexpected HTTP response code {res['code']} from Abuse.ch Abuse.ch Feodo Tracker.")
            self.errorState = True
            return None

        if res['content'] is None:
            self.error("Received no content from Abuse.ch Feodo Tracker")
            self.errorState = True
            return None

        self.sf.cachePut("abusech_ssl", res['content'])

        return self.parseSslBlacklist(res['content'])

    def parseSslBlacklist(self, blacklist):
        """Parse plaintext blacklist

        Args:
            blacklist (str): CSV blacklist from Abuse.ch SSL Blacklist

        Returns:
            list: list of blacklisted IP addresses
        """
        ips = list()

        if not blacklist:
            return ips

        for line in blacklist.split('\n'):
            line = line.strip()
            if not line:
                continue
            if line.startswith('#'):
                continue
            csv = line.split(',')
            if len(csv) < 2:
                continue
            ip = csv[1]
            if not self.sf.validIP(ip):
                continue
            ips.append(ip)

        return ips

    def queryUrlHausBlacklist(self, target, targetType):
        blacklist = self.retrieveUrlHausBlacklist()

        if not blacklist:
            return False

        if targetType == "ip":
            if target in blacklist:
                self.debug(f"IP address {target} found in Abuse.ch URL Haus Blacklist.")
                return True
        elif targetType == "netblock":
            netblock = IPNetwork(target)
            for ip in blacklist:
                if IPAddress(ip) in netblock:
                    self.debug(f"IP address {ip} found within netblock/subnet {target} in Abuse.ch URL Haus Blacklist.")
                    return True
        elif targetType == "domain":
            if target.lower() in blacklist:
                self.debug(f"Host name {target} found in Abuse.ch URL Haus Blacklist.")
                return True

        return False

    def retrieveUrlHausBlacklist(self):
        blacklist = self.sf.cacheGet('abusech_urlhaus', 24)

        if blacklist is not None:
            return self.parseUrlHausBlacklist(blacklist)

        res = self.sf.fetchUrl(
            "https://urlhaus.abuse.ch/downloads/csv_recent/",
            timeout=self.opts['_fetchtimeout'],
            useragent=self.opts['_useragent'],
        )

        if res['code'] != "200":
            self.error(f"Unexpected HTTP response code {res['code']} from Abuse.ch URL Haus.")
            self.errorState = True
            return None

        if res['content'] is None:
            self.error("Received no content from Abuse.ch URL Haus")
            self.errorState = True
            return None

        self.sf.cachePut("abusech_urlhaus", res['content'])

        return self.parseUrlHausBlacklist(res['content'])

    def parseUrlHausBlacklist(self, blacklist):
        """Parse plaintext blacklist

        Args:
            blacklist (str): plaintext blacklist from Abuse.ch URL Haus

        Returns:
            list: list of blacklisted hosts
        """
        hosts = list()

        if not blacklist:
            return hosts

        for line in blacklist.split('\n'):
            if not line:
                continue
            if line.startswith('#'):
                continue

            # Note: URL parsing and validation with sf.validHost() is too slow to use here
            url = line.strip().lower()
            if len(url.split("/")) < 3:
                continue
            host = url.split("/")[2].split(':')[0]
            if not host:
                continue
            if "." not in host:
                continue
            hosts.append(host)

        return hosts

    def handleEvent(self, event):
        eventName = event.eventType
        srcModuleName = event.module
        eventData = event.data

        self.debug(f"Received event, {eventName}, from {srcModuleName}")

        if eventData in self.results:
            self.debug(f"Skipping {eventData}, already checked.")
            return

        if self.errorState:
            return

        self.results[eventData] = True

        if eventName == 'IP_ADDRESS':
            targetType = 'ip'
            evtType = 'MALICIOUS_IPADDR'
        elif eventName == 'AFFILIATE_IPADDR':
            if not self.opts.get('checkaffiliates', False):
                return
            targetType = 'ip'
            evtType = 'MALICIOUS_AFFILIATE_IPADDR'
        elif eventName == 'NETBLOCK_OWNER':
            if not self.opts.get('checknetblocks', False):
                return
            targetType = 'netblock'
            evtType = 'MALICIOUS_NETBLOCK'
        elif eventName == 'NETBLOCK_MEMBER':
            if not self.opts.get('checksubnets', False):
                return
            targetType = 'netblock'
            evtType = 'MALICIOUS_SUBNET'
        elif eventName == "INTERNET_NAME":
            targetType = 'domain'
            evtType = "MALICIOUS_INTERNET_NAME"
        elif eventName == 'AFFILIATE_INTERNET_NAME':
            if not self.opts.get('checkaffiliates', False):
                return
            targetType = 'domain'
            evtType = 'MALICIOUS_AFFILIATE_INTERNET_NAME'
        elif eventName == 'CO_HOSTED_SITE':
            if not self.opts.get('checkcohosts', False):
                return
            targetType = 'domain'
            evtType = 'MALICIOUS_COHOST'
        else:
            return

        if targetType in ['ip', 'netblock']:
            self.debug(f"Checking maliciousness of {eventData} ({eventName}) with Abuse.ch Feodo Tracker")
            if self.queryFeodoTrackerBlacklist(eventData, targetType):
                url = "https://feodotracker.abuse.ch/downloads/ipblocklist.txt"
                text = f"Abuse.ch Feodo Tracker [{eventData}]\n<SFURL>{url}</SFURL>"
                evt = SpiderFootEvent(evtType, text, self.__name__, event)
                self.notifyListeners(evt)

            self.debug(f"Checking maliciousness of {eventData} ({eventName}) with Abuse.ch SSL Blacklist")
            if self.querySslBlacklist(eventData, targetType):
                url = "https://sslbl.abuse.ch/blacklist/sslipblacklist.csv"
                text = f"Abuse.ch SSL Blacklist [{eventData}]\n<SFURL>{url}</SFURL>"
                evt = SpiderFootEvent(evtType, text, self.__name__, event)
                self.notifyListeners(evt)

        if targetType in ['ip', 'domain']:
            self.debug(f"Checking maliciousness of {eventData} ({eventName}) with Abuse.ch URL Haus")
            if self.queryUrlHausBlacklist(eventData, targetType):
                url = "https://urlhaus.abuse.ch/downloads/csv_recent/"
                text = f"Abuse.ch URL Haus Blacklist [{eventData}]\n<SFURL>{url}</SFURL>"
                evt = SpiderFootEvent(evtType, text, self.__name__, event)
                self.notifyListeners(evt)

# End of sfp_abusech class


================================================
FILE: modules/sfp_abuseipdb.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:        sfp_abuseipdb
# Purpose:     Check if an IP address is malicious according to AbuseIPDB.com.
#
# Author:      steve@binarypool.com
#
# Created:     06/09/2018
# Copyright:   (c) Steve Micallef, 2018
# Licence:     MIT
# -------------------------------------------------------------------------------

import json
import time
import urllib.error
import urllib.parse
import urllib.request

from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_abuseipdb(SpiderFootPlugin):

    meta = {
        'name': "AbuseIPDB",
        'summary': "Check if an IP address is malicious according to AbuseIPDB.com blacklist.",
        'flags': ["apikey"],
        'useCases': ["Passive", "Investigate"],
        'categories': ["Reputation Systems"],
        'dataSource': {
            'website': "https://www.abuseipdb.com",
            'model': "FREE_AUTH_LIMITED",
            'references': [
                "https://docs.abuseipdb.com/#introduction",
                "https://www.abuseipdb.com/fail2ban.html",
                "https://www.abuseipdb.com/csf",
                "https://www.abuseipdb.com/suricata",
                "https://www.abuseipdb.com/splunk",
                "https://www.abuseipdb.com/categories"
            ],
            'apiKeyInstructions': [
                "Visit https://www.abuseipdb.com/pricing",
                "Select the plan required",
                "Register a new account with an email",
                "Navigate to https://www.abuseipdb.com/account/api",
                "The API Key is listed under 'Keys'"
            ],
            'favIcon': "https://www.abuseipdb.com/favicon.ico",
            'logo': "https://www.abuseipdb.com/img/abuseipdb.png.pagespeed.ce.CI8T6WsXU7.png",
            'description': "AbuseIPDB is a project dedicated to helping combat the spread of hackers,"
            "spammers, and abusive activity on the internet.\n"
            "Our mission is to help make Web safer by providing a central blacklist for"
            "webmasters, system administrators, and other interested parties to"
            "report and find IP addresses that have been associated with malicious activity online."
        }
    }

    opts = {
        'api_key': '',
        'confidenceminimum': 90,
        'checkaffiliates': True,
        'limit': 10000
    }

    optdescs = {
        'api_key': "AbuseIPDB.com API key.",
        'confidenceminimum': "The minimium AbuseIPDB confidence level to require.",
        'checkaffiliates': "Apply checks to affiliates?",
        'limit': 'Maximum number of results to retrieve.',
    }

    results = None

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc
        self.results = self.tempStorage()

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    def watchedEvents(self):
        return [
            "IP_ADDRESS",
            "IPV6_ADDRESS",
            "AFFILIATE_IPADDR",
            "AFFILIATE_IPV6_ADDRESS",
        ]

    def producedEvents(self):
        return [
            "BLACKLISTED_IPADDR",
            "BLACKLISTED_AFFILIATE_IPADDR",
            "MALICIOUS_IPADDR",
            "MALICIOUS_AFFILIATE_IPADDR",
        ]

    def queryBlacklist(self):
        blacklist = self.sf.cacheGet('abuseipdb', 24)

        if blacklist is not None:
            return self.parseBlacklist(blacklist)

        headers = {
            'Key': self.opts['api_key'],
            'Accept': "text/plain"
        }

        params = urllib.parse.urlencode({
            'confidenceMinimum': self.opts['confidenceminimum'],
            'limit': self.opts['limit'],
            'plaintext': '1'
        })

        res = self.sf.fetchUrl(
            f"https://api.abuseipdb.com/api/v2/blacklist?{params}",
            timeout=60,  # retrieving 10,000 results (default) or more can sometimes take a while
            useragent=self.opts['_useragent'],
            headers=headers
        )

        time.sleep(1)

        if res['code'] == '429':
            self.error("You are being rate-limited by AbuseIPDB")
            self.errorState = True
            return None

        if res['code'] != "200":
            self.error(f"Error retrieving search results, code {res['code']}")
            self.errorState = True
            return None

        if res['code'] != "200":
            self.error("Error retrieving search results from AbuseIPDB")
            self.errorState = True
            return None

        if res['content'] is None:
            self.error("Received no content from AbuseIPDB")
            self.errorState = True
            return None

        self.sf.cachePut("abuseipdb", res['content'])

        return self.parseBlacklist(res['content'])

    def parseBlacklist(self, blacklist):
        """Parse plaintext blacklist

        Args:
            blacklist (str): plaintext blacklist from AbuseIPDB

        Returns:
            list: list of blacklisted IP addresses
        """
        ips = list()

        if not blacklist:
            return ips

        for ip in blacklist.split('\n'):
            ip = ip.strip()
            if ip.startswith('#'):
                continue
            if not self.sf.validIP(ip) and not self.sf.validIP6(ip):
                continue
            ips.append(ip)

        return ips

    def queryIpAddress(self, ip):
        """Query API for an IPv4 or IPv6 address.

        Note: Currently unused.

        Args:
            ip (str): IP address

        Returns:
            str: API response as JSON
        """

        headers = {
            'Key': self.opts['api_key'],
            'Accept': 'application/json',
        }

        params = urllib.parse.urlencode({
            'ipAddress': ip,
            'maxAgeInDays': 30,
        })

        res = self.sf.fetchUrl(
            f"https://api.abuseipdb.com/api/v2/check?{params}",
            timeout=self.opts['_fetchtimeout'],
            useragent=self.opts['_useragent'],
            headers=headers
        )

        time.sleep(1)

        if res['code'] == '429':
            self.error("You are being rate-limited by AbuseIPDB")
            self.errorState = True
            return None

        if res['code'] != "200":
            self.error("Error retrieving search results from AbuseIPDB")
            self.errorState = True
            return None

        if res['content'] is None:
            self.error("Received no content from AbuseIPDB")
            self.errorState = True
            return None

        try:
            return json.loads(res['content'])
        except Exception as e:
            self.debug(f"Error processing JSON response: {e}")
            return None

        return None

    def queryNetblock(self, ip):
        """Query API for a netblock.

        Note: Currently unused.

        Args:
            ip (str): CIDR range

        Returns:
            str: API response as JSON
        """

        headers = {
            'Key': self.opts['api_key'],
            'Accept': 'application/json',
        }

        params = urllib.parse.urlencode({
            'ipAddress': ip,
            'maxAgeInDays': 30,
        })

        res = self.sf.fetchUrl(
            f"https://api.abuseipdb.com/api/v2/check-block?{params}",
            timeout=self.opts['_fetchtimeout'],
            useragent=self.opts['_useragent'],
            headers=headers
        )

        time.sleep(1)

        if res['code'] == '429':
            self.error("You are being rate-limited by AbuseIPDB")
            self.errorState = True
            return None

        if res['code'] != "200":
            self.error("Error retrieving search results from AbuseIPDB")
            self.errorState = True
            return None

        if res['content'] is None:
            self.error("Received no content from AbuseIPDB")
            self.errorState = True
            return None

        try:
            return json.loads(res['content'])
        except Exception as e:
            self.debug(f"Error processing JSON response: {e}")

        return None

    def handleEvent(self, event):
        eventName = event.eventType
        srcModuleName = event.module
        eventData = event.data

        self.debug(f"Received event, {eventName}, from {srcModuleName}")

        if self.opts["api_key"] == "":
            self.error(
                f"You enabled {self.__class__.__name__} but did not set an API key!"
            )
            self.errorState = True
            return

        if eventData in self.results:
            self.debug(f"Skipping {eventData}, already checked.")
            return

        self.results[eventData] = True

        if eventName.startswith("AFFILIATE") and not self.opts['checkaffiliates']:
            return

        if eventName in ['IP_ADDRESS', 'IPV6_ADDRESS']:
            blacklist_type = "BLACKLISTED_IPADDR"
            malicious_type = 'MALICIOUS_IPADDR'
        elif eventName in ['AFFILIATE_IPADDR', 'AFFILIATE_IPV6_ADDRESS']:
            blacklist_type = "BLACKLISTED_AFFILIATE_IPADDR"
            malicious_type = 'MALICIOUS_AFFILIATE_IPADDR'
        else:
            self.debug(f"Unexpected event type {eventName}, skipping")
            return

        self.debug(f"Checking maliciousness of IP address {eventData} with AbuseIPDB")

        blacklist = self.queryBlacklist()

        if not blacklist:
            return

        if eventData not in blacklist:
            return

        self.info(f"Malicious IP address {eventData} found in AbuseIPDB blacklist")

        url = f"https://www.abuseipdb.com/check/{eventData}"

        evt = SpiderFootEvent(
            malicious_type,
            f"AbuseIPDB [{eventData}]\n<SFURL>{url}</SFURL>",
            self.__name__,
            event
        )
        self.notifyListeners(evt)

        evt = SpiderFootEvent(
            blacklist_type,
            f"AbuseIPDB [{eventData}]\n<SFURL>{url}</SFURL>",
            self.__name__,
            event
        )
        self.notifyListeners(evt)

# End of sfp_abuseipdb class


================================================
FILE: modules/sfp_abusix.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:        sfp_abusix
# Purpose:     SpiderFoot plug-in for looking up whether IPs/Netblocks/Domains
#              appear in the Abusix Mail Intelligence blacklist.
#
# Author:      <bcoles@gmail.com>
#
# Created:     2021-10-17
# Copyright:   (c) bcoles 2021
# Licence:     MIT
# -------------------------------------------------------------------------------

import ipaddress

from netaddr import IPNetwork

from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_abusix(SpiderFootPlugin):

    meta = {
        'name': "Abusix Mail Intelligence",
        'summary': "Check if a netblock or IP address is in the Abusix Mail Intelligence blacklist.",
        'flags': ['apikey'],
        'useCases': ["Investigate", "Passive"],
        'categories': ["Reputation Systems"],
        'dataSource': {
            'website': "https://abusix.org/",
            'model': "FREE_AUTH_LIMITED",
            'references': [
                "https://abusix.com/products/abusix-mail-intelligence/",
                "https://docs.abusix.com/105726-setup-abusix-mail-intelligence/ami%2Fsetup%2Fexample-queries",
                "https://docs.abusix.com/105725-detailed-list-information/ami%2Freturn-codes",
            ],
            'apiKeyInstructions': [
                "Visit https://app.abusix.com/signup",
                "Register a free account",
                "Browse to 'Account Settings' page",
                "The API key is listed on the 'Email protection' page."
            ],
            'logo': "https://abusix.com/wp-content/uploads/2020/10/Footer_logo.png",
            'description': "Abusix Mail Intelligence is an innovative set of blocklists (RBL/DNSBL) "
            "that adds real-time threat data to your existing email protection. "
            "Considered as the first line of defense, blocklists help to prevent email-borne threats "
            "such as spam and malware from entering your network."
        }
    }

    opts = {
        'api_key': "",
        'checkaffiliates': True,
        'checkcohosts': True,
        'netblocklookup': True,
        'maxnetblock': 24,
        'maxv6netblock': 120,
        'subnetlookup': True,
        'maxsubnet': 24,
        'maxv6subnet': 120,
    }

    optdescs = {
        'api_key': "Abusix Mail Intelligence API key.",
        'checkaffiliates': "Apply checks to affiliates?",
        'checkcohosts': "Apply checks to sites found to be co-hosted on the target's IP?",
        'netblocklookup': "Look up all IPs on netblocks deemed to be owned by your target for possible blacklisted hosts on the same target subdomain/domain?",
        'maxnetblock': "If looking up owned netblocks, the maximum netblock size to look up all IPs within (CIDR value, 24 = /24, 16 = /16, etc.)",
        'maxv6netblock': "If looking up owned netblocks, the maximum IPv6 netblock size to look up all IPs within (CIDR value, 24 = /24, 16 = /16, etc.)",
        'subnetlookup': "Look up all IPs on subnets which your target is a part of for blacklisting?",
        'maxsubnet': "If looking up subnets, the maximum subnet size to look up all the IPs within (CIDR value, 24 = /24, 16 = /16, etc.)",
        'maxv6subnet': "If looking up subnets, the maximum IPv6 subnet size to look up all the IPs within (CIDR value, 24 = /24, 16 = /16, etc.)",
    }

    results = None
    errorState = False

    checks = {
        "127.0.0.2": "black",
        "127.0.0.3": "black (composite/heuristic)",
        "127.0.0.4": "exploit / authbl",
        "127.0.0.5": "forged",
        "127.0.0.6": "backscatter",
        "127.0.0.11": "policy (generic rDNS)",
        "127.0.0.12": "policy (missing rDNS)",
        "127.0.0.100": "noip",
        "127.0.1.1": "dblack",
        "127.0.1.2": "dblack (Newly Observed Domain)",
        "127.0.1.3": "dblack (Unshortened)",
        "127.0.2.1": "white",
        "127.0.3.1": "shorthash",
        "127.0.3.2": "diskhash",
        "127.0.4.1": "btc-wallets",
        "127.0.5.1": "attachhash",
    }

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc
        self.errorState = False
        self.results = self.tempStorage()

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    def watchedEvents(self):
        return [
            'IP_ADDRESS',
            'IPV6_ADDRESS',
            'AFFILIATE_IPADDR',
            'AFFILIATE_IPV6_ADDRESS',
            "NETBLOCK_MEMBER",
            "NETBLOCKV6_MEMBER",
            "NETBLOCK_OWNER",
            "NETBLOCKV6_OWNER",
            'INTERNET_NAME',
            'AFFILIATE_INTERNET_NAME',
            'CO_HOSTED_SITE',
        ]

    def producedEvents(self):
        return [
            "BLACKLISTED_IPADDR",
            "BLACKLISTED_AFFILIATE_IPADDR",
            "BLACKLISTED_SUBNET",
            "BLACKLISTED_NETBLOCK",
            "BLACKLISTED_INTERNET_NAME",
            "BLACKLISTED_AFFILIATE_INTERNET_NAME",
            "BLACKLISTED_COHOST",
            "MALICIOUS_IPADDR",
            "MALICIOUS_AFFILIATE_IPADDR",
            "MALICIOUS_NETBLOCK",
            "MALICIOUS_SUBNET",
            "MALICIOUS_INTERNET_NAME",
            "MALICIOUS_AFFILIATE_INTERNET_NAME",
            "MALICIOUS_COHOST",
        ]

    def reverseIpAddress(self, ipaddr):
        if not self.sf.validIP(ipaddr):
            self.debug(f"Invalid IPv4 address {ipaddr}")
            return None
        return ipaddress.ip_address(ipaddr).reverse_pointer.replace('.in-addr.arpa', '')

    def reverseIp6Address(self, ipaddr):
        if not self.sf.validIP6(ipaddr):
            self.debug(f"Invalid IPv6 address {ipaddr}")
            return None
        return ipaddress.ip_address(ipaddr).reverse_pointer.replace('.ip6.arpa', '')

    def query(self, qaddr):
        """Query Abusix Mail Intelligence DNS.

        Args:
            qaddr (str): Host name or IPv4 address.

        Returns:
            list: Abusix DNS entries
        """
        if self.sf.validIP(qaddr):
            lookup = f"{self.reverseIpAddress(qaddr)}.{self.opts['api_key']}.combined.mail.abusix.zone"
        elif self.sf.validIP6(qaddr):
            lookup = f"{self.reverseIp6Address(qaddr)}.{self.opts['api_key']}.combined.mail.abusix.zone"
        else:
            lookup = f"{qaddr}.{self.opts['api_key']}.combined.mail.abusix.zone"

        self.debug(f"Checking Abusix Mail Intelligence blacklist: {lookup}")

        try:
            return self.sf.resolveHost(lookup)
        except Exception as e:
            self.debug(f"Abusix Mail Intelligence did not resolve {qaddr} / {lookup}: {e}")

        return None

    def handleEvent(self, event):
        eventName = event.eventType
        eventData = event.data

        if self.errorState:
            return

        self.debug(f"Received event, {eventName}, from {event.module}")

        if not self.opts['api_key']:
            self.error(f"You enabled {self.__class__.__name__} but did not set an API key!")
            self.errorState = True
            return

        if eventData in self.results:
            return

        self.results[eventData] = True

        if eventName in ['AFFILIATE_IPADDR', 'AFFILIATE_IPV6_ADDRESS']:
            if not self.opts.get('checkaffiliates', False):
                return
            malicious_type = "MALICIOUS_AFFILIATE_IPADDR"
            blacklist_type = "BLACKLISTED_AFFILIATE_IPADDR"
        elif eventName in ['IP_ADDRESS', 'IPV6_ADDRESS']:
            malicious_type = "MALICIOUS_IPADDR"
            blacklist_type = "BLACKLISTED_IPADDR"
        elif eventName in ['NETBLOCK_MEMBER', 'NETBLOCKV6_MEMBER']:
            if not self.opts['subnetlookup']:
                return

            if eventName == 'NETBLOCKV6_MEMBER':
                max_subnet = self.opts['maxv6subnet']
            else:
                max_subnet = self.opts['maxsubnet']

            if IPNetwork(eventData).prefixlen < max_subnet:
                self.debug(f"Network size bigger than permitted: {IPNetwork(eventData).prefixlen} > {max_subnet}")
                return

            malicious_type = "MALICIOUS_SUBNET"
            blacklist_type = "BLACKLISTED_SUBNET"
        elif eventName in ['NETBLOCK_OWNER', 'NETBLOCKV6_OWNER']:
            if not self.opts['netblocklookup']:
                return

            if eventName == 'NETBLOCKV6_OWNER':
                max_netblock = self.opts['maxv6netblock']
            else:
                max_netblock = self.opts['maxnetblock']

            if IPNetwork(eventData).prefixlen < max_netblock:
                self.debug(f"Network size bigger than permitted: {IPNetwork(eventData).prefixlen} > {max_netblock}")
                return

            malicious_type = "MALICIOUS_NETBLOCK"
            blacklist_type = "BLACKLISTED_NETBLOCK"
        elif eventName == "INTERNET_NAME":
            malicious_type = "MALICIOUS_INTERNET_NAME"
            blacklist_type = "BLACKLISTED_INTERNET_NAME"
        elif eventName == "AFFILIATE_INTERNET_NAME":
            if not self.opts.get('checkaffiliates', False):
                return
            malicious_type = "MALICIOUS_AFFILIATE_INTERNET_NAME"
            blacklist_type = "BLACKLISTED_AFFILIATE_INTERNET_NAME"
        elif eventName == "CO_HOSTED_SITE":
            if not self.opts.get('checkcohosts', False):
                return
            malicious_type = "MALICIOUS_COHOST"
            blacklist_type = "BLACKLISTED_COHOST"
        else:
            self.debug(f"Unexpected event type {eventName}, skipping")
            return

        addrs = list()
        if eventName.startswith("NETBLOCK"):
            for addr in IPNetwork(eventData):
                addrs.append(str(addr))
        else:
            addrs.append(eventData)

        for addr in addrs:
            if self.checkForStop():
                return

            if self.errorState:
                return

            res = self.query(addr)

            self.results[addr] = True

            if not res:
                continue

            self.debug(f"{addr} found in Abusix Mail Intelligence DNS")

            for result in res:
                k = str(result)

                if k not in self.checks:
                    if 'mail.abusix.zone' not in result:
                        # This is an error. The "checks" dict may need to be updated.
                        self.error(f"Abusix Mail Intelligence resolved address {addr} to unknown IP address {result} not found in Abusix Mail Intelligence list.")
                    continue

                text = f"Abusix Mail Intelligence - {self.checks[k]} [{addr}]\n<SFURL>https://lookup.abusix.com/search?q={addr}</SFURL>"

                evt = SpiderFootEvent(blacklist_type, text, self.__name__, event)
                self.notifyListeners(evt)

                evt = SpiderFootEvent(malicious_type, text, self.__name__, event)
                self.notifyListeners(evt)

# End of sfp_abusix class


================================================
FILE: modules/sfp_accounts.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:         sfp_accounts
# Purpose:      Identify the existence of a given acount on various sites thanks
#               to Micah Hoffman's (https://github.com/WebBreacher) list.
#
# Author:      Steve Micallef <steve@binarypool.com>
#
# Created:     18/02/2015
# Copyright:   (c) Steve Micallef 2015
# Licence:     MIT
# -------------------------------------------------------------------------------

import json
import random
import threading
import time
from queue import Empty as QueueEmpty
from queue import Queue

from spiderfoot import SpiderFootEvent, SpiderFootHelpers, SpiderFootPlugin


class sfp_accounts(SpiderFootPlugin):

    meta = {
        'name': "Account Finder",
        'summary': "Look for possible associated accounts on over 500 social and other websites such as Instagram, Reddit, etc.",
        'useCases': ["Footprint", "Passive"],
        'categories': ["Social Media"]
    }

    # Default options
    opts = {
        "ignorenamedict": True,
        "ignoreworddict": True,
        "musthavename": True,
        "userfromemail": True,
        "permutate": False,
        "usernamesize": 4,
        "_maxthreads": 20
    }

    # Option descriptions
    optdescs = {
        "ignorenamedict": "Don't bother looking up names that are just stand-alone first names (too many false positives).",
        "ignoreworddict": "Don't bother looking up names that appear in the dictionary.",
        "musthavename": "The username must be mentioned on the social media page to consider it valid (helps avoid false positives).",
        "userfromemail": "Extract usernames from e-mail addresses at all? If disabled this can reduce false positives for common usernames but for highly unique usernames it would result in missed accounts.",
        "permutate": "Look for the existence of account name permutations. Useful to identify fraudulent social media accounts or account squatting.",
        "usernamesize": "The minimum length of a username to query across social media sites. Helps avoid false positives for very common short usernames.",
        "_maxthreads": "Maximum threads"
    }

    results = None
    reportedUsers = list()
    siteResults = dict()
    sites = list()
    errorState = False
    distrustedChecked = False
    lock = None

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc
        self.results = self.tempStorage()
        self.commonNames = list()
        self.reportedUsers = list()
        self.errorState = False
        self.distrustedChecked = False
        self.__dataSource__ = "Social Media"
        self.lock = threading.Lock()

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

        self.commonNames = SpiderFootHelpers.humanNamesFromWordlists()
        self.words = SpiderFootHelpers.dictionaryWordsFromWordlists()

        content = self.sf.cacheGet("sfaccountsv2", 48)
        if content is None:
            url = "https://raw.githubusercontent.com/WebBreacher/WhatsMyName/main/wmn-data.json"
            data = self.sf.fetchUrl(url, useragent="SpiderFoot")

            if data['content'] is None:
                self.error(f"Unable to fetch {url}")
                self.errorState = True
                return

            content = data['content']
            self.sf.cachePut("sfaccountsv2", content)

        try:
            self.sites = [site for site in json.loads(content)['sites'] if not site.get('valid', True) is False]
        except Exception as e:
            self.error(f"Unable to parse social media accounts list: {e}")
            self.errorState = True
            return

    def watchedEvents(self):
        return ["EMAILADDR", "DOMAIN_NAME", "HUMAN_NAME", "USERNAME"]

    def producedEvents(self):
        return ["USERNAME", "ACCOUNT_EXTERNAL_OWNED",
                "SIMILAR_ACCOUNT_EXTERNAL"]

    def checkSite(self, name, site):
        if 'uri_check' not in site:
            return

        url = site['uri_check'].format(account=name)
        if 'uri_pretty' in site:
            ret_url = site['uri_pretty'].format(account=name)
        else:
            ret_url = url
        retname = f"{site['name']} (Category: {site['cat']})\n<SFURL>{ret_url}</SFURL>"

        post = None
        if site.get('post_body'):
            post = site['post_body']

        res = self.sf.fetchUrl(
            url,
            postData=post,
            timeout=self.opts['_fetchtimeout'],
            useragent=self.opts['_useragent'],
            noLog=True,
            verify=False
        )

        if not res['content']:
            with self.lock:
                self.siteResults[retname] = False
            return

        if site.get('e_code') != site.get('m_code'):
            if res['code'] != str(site.get('e_code')):
                with self.lock:
                    self.siteResults[retname] = False
                return

        if site.get('e_string') not in res['content'] or (site.get('m_string') and site.get('m_string') in res['content']):
            with self.lock:
                self.siteResults[retname] = False
            return

        if self.opts['musthavename']:
            if name.lower() not in res['content'].lower():
                self.debug(f"Skipping {site['name']} as username not mentioned.")
                with self.lock:
                    self.siteResults[retname] = False
                return

        # Some sites can't handle periods so treat bob.abc and bob as the same
        # TODO: fix this once WhatsMyName has support for usernames with '.'
        if "." in name:
            firstname = name.split(".")[0]
            if firstname + "<" in res['content'] or firstname + '"' in res['content']:
                with self.lock:
                    self.siteResults[retname] = False
                return

        with self.lock:
            self.siteResults[retname] = True

    def checkSites(self, username, sites=None):
        def processSiteQueue(username, queue):
            try:
                while True:
                    site = queue.get(timeout=0.1)
                    try:
                        self.checkSite(username, site)
                    except Exception as e:
                        self.debug(f'Thread {threading.current_thread().name} exception: {e}')
            except QueueEmpty:
                return

        startTime = time.monotonic()

        # results will be collected in siteResults
        self.siteResults = {}

        sites = self.sites if sites is None else sites

        # load the queue
        queue = Queue()
        for site in sites:
            queue.put(site)

        # start the scan threads
        threads = []
        for i in range(min(len(sites), self.opts['_maxthreads'])):
            thread = threading.Thread(
                name=f'sfp_accounts_scan_{i}',
                target=processSiteQueue,
                args=(username, queue))
            thread.start()
            threads.append(thread)

        # wait for all scan threads to finish
        while threads:
            threads.pop(0).join()

        duration = time.monotonic() - startTime
        scanRate = len(sites) / duration
        self.debug(f'Scan statistics: name={username}, count={len(self.siteResults)}, duration={duration:.2f}, rate={scanRate:.0f}')

        return [site for site, found in self.siteResults.items() if found]

    def generatePermutations(self, username):
        permutations = list()
        prefixsuffix = ['_', '-']
        replacements = {
            'a': ['4', 's'],
            'b': ['v', 'n'],
            'c': ['x', 'v'],
            'd': ['s', 'f'],
            'e': ['w', 'r'],
            'f': ['d', 'g'],
            'g': ['f', 'h'],
            'h': ['g', 'j', 'n'],
            'i': ['o', 'u', '1'],
            'j': ['k', 'h', 'i'],
            'k': ['l', 'j'],
            'l': ['i', '1', 'k'],
            'm': ['n'],
            'n': ['m'],
            'o': ['p', 'i', '0'],
            'p': ['o', 'q'],
            'r': ['t', 'e'],
            's': ['a', 'd', '5'],
            't': ['7', 'y', 'z', 'r'],
            'u': ['v', 'i', 'y', 'z'],
            'v': ['u', 'c', 'b'],
            'w': ['v', 'vv', 'q', 'e'],
            'x': ['z', 'y', 'c'],
            'y': ['z', 'x'],
            'z': ['y', 'x'],
            '0': ['o'],
            '1': ['l'],
            '2': ['5'],
            '3': ['e'],
            '4': ['a'],
            '5': ['s'],
            '6': ['b'],
            '7': ['t'],
            '8': ['b'],
            '9': []
        }
        pairs = {
            'oo': ['00'],
            'll': ['l1l', 'l1l', '111', '11'],
            '11': ['ll', 'lll', 'l1l', '1l1']
        }

        # Generate a set with replacements, then
        # add suffixes and prefixes.
        pos = 0
        for c in username:
            if c not in replacements:
                continue
            if len(replacements[c]) == 0:
                continue
            npos = pos + 1
            for xc in replacements[c]:
                newuser = username[0:pos] + xc + username[npos:len(username)]
                permutations.append(newuser)

            pos += 1

        # Search for common double-letter replacements
        for p in pairs:
            if p in username:
                for r in pairs[p]:
                    permutations.append(username.replace(p, r))

        # Search for prefixed and suffixed usernames
        for c in prefixsuffix:
            permutations.append(username + c)
            permutations.append(c + username)

        # Search for double character usernames
        pos = 0
        for c in username:
            permutations.append(username[0:pos] + c + c + username[(pos + 1):len(username)])
            pos += 1

        return list(set(permutations))

    def handleEvent(self, event):
        eventName = event.eventType
        srcModuleName = event.module
        eventData = event.data
        users = list()

        if self.errorState:
            return

        self.debug(f"Received event, {eventName}, from {srcModuleName}")

        # Skip events coming from me unless they are USERNAME events
        if eventName != "USERNAME" and srcModuleName == "sfp_accounts":
            self.debug(f"Ignoring {eventName}, from self.")
            return

        if eventData in list(self.results.keys()):
            return

        self.results[eventData] = True

        # If being called for the first time, let's see how trusted the
        # sites are by attempting to fetch a garbage user.
        if not self.distrustedChecked:
            # Check if a state cache exists first, to not have to do this all the time
            content = self.sf.cacheGet("sfaccounts_state_v3", 72)
            if content:
                if content != "None":  # "None" is written to the cached file when no sites are distrusted
                    delsites = list()
                    for line in content.split("\n"):
                        if line == '':
                            continue
                        delsites.append(line)
                    self.sites = [d for d in self.sites if d['name'] not in delsites]
            else:
                randpool = 'abcdefghijklmnopqrstuvwxyz1234567890'
                randuser = ''.join([random.SystemRandom().choice(randpool) for x in range(10)])
                res = self.checkSites(randuser)
                if res:
                    delsites = list()
                    for site in res:
                        sitename = site.split(" (Category:")[0]
                        self.debug(f"Distrusting {sitename}")
                        delsites.append(sitename)
                    self.sites = [d for d in self.sites if d['name'] not in delsites]
                else:
                    # The caching code needs *some* content
                    delsites = "None"
                self.sf.cachePut("sfaccounts_state_v3", delsites)

            self.distrustedChecked = True

        if eventName == "HUMAN_NAME":
            names = [eventData.lower().replace(" ", ""), eventData.lower().replace(" ", ".")]
            for name in names:
                users.append(name)

        if eventName == "DOMAIN_NAME":
            kw = self.sf.domainKeyword(eventData, self.opts['_internettlds'])
            if not kw:
                return

            users.append(kw)

        if eventName == "EMAILADDR" and self.opts['userfromemail']:
            name = eventData.split("@")[0].lower()
            users.append(name)

        if eventName == "USERNAME":
            users.append(eventData)

        for user in set(users):
            if user in self.opts['_genericusers'].split(","):
                self.debug(f"{user} is a generic account name, skipping.")
                continue

            if self.opts['ignorenamedict'] and user in self.commonNames:
                self.debug(f"{user} is found in our name dictionary, skipping.")
                continue

            if self.opts['ignoreworddict'] and user in self.words:
                self.debug(f"{user} is found in our word dictionary, skipping.")
                continue

            if user not in self.reportedUsers and eventData != user:
                if len(user) < self.opts['usernamesize']:
                    self.debug(f"{user} is too short, skipping.")
                    continue

                evt = SpiderFootEvent("USERNAME", user, self.__name__, event)
                self.notifyListeners(evt)
                self.reportedUsers.append(user)

        # Only look up accounts when we've received a USERNAME event (possibly from
        # ourselves), since we want them to have gone through some verification by
        # this module, and we don't want duplicates (one based on EMAILADDR and another
        # based on USERNAME).
        if eventName == "USERNAME":
            res = self.checkSites(user)
            for site in res:
                evt = SpiderFootEvent(
                    "ACCOUNT_EXTERNAL_OWNED",
                    site,
                    self.__name__,
                    event
                )
                self.notifyListeners(evt)

            if self.opts['permutate']:
                permutations = self.generatePermutations(user)
                for puser in permutations:
                    res = self.checkSites(puser)
                    for site in res:
                        evt = SpiderFootEvent(
                            "SIMILAR_ACCOUNT_EXTERNAL",
                            site,
                            self.__name__,
                            event
                        )
                        self.notifyListeners(evt)
# End of sfp_accounts class


================================================
FILE: modules/sfp_adblock.py
================================================
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name:         sfp_adblock
# Purpose:      SpiderFoot plug-in to test if external/internally linked pages
#               would be blocked by AdBlock Plus.
#
# Author:      Steve Micallef <steve@binarypool.com>
#
# Created:     22/09/2014
# Copyright:   (c) Steve Micallef 2014
# Licence:     MIT
# -------------------------------------------------------------------------------

import adblockparser

from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_adblock(SpiderFootPlugin):

    meta = {
        'name': "AdBlock Check",
        'summary': "Check if linked pages would be blocked by AdBlock Plus.",
        'useCases': ["Investigate", "Passive"],
Download .txt
gitextract_l429po4y/

├── .dockerignore
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       ├── codeql-analysis.yml
│       └── tests.yaml
├── .gitignore
├── .pylintrc
├── Dockerfile
├── Dockerfile.full
├── LICENSE
├── README.md
├── THANKYOU
├── VERSION
├── correlations/
│   ├── README.md
│   ├── cert_expired.yaml
│   ├── cloud_bucket_open.yaml
│   ├── cloud_bucket_open_related.yaml
│   ├── data_from_base64.yaml
│   ├── data_from_docmeta.yaml
│   ├── database_exposed.yaml
│   ├── dev_or_test_system.yaml
│   ├── dns_zone_transfer_possible.yaml
│   ├── egress_ip_from_wikipedia.yaml
│   ├── email_in_multiple_breaches.yaml
│   ├── email_in_whois.yaml
│   ├── email_only_from_pasteleak_site.yaml
│   ├── host_only_from_bruteforce.yaml
│   ├── host_only_from_certificatetransparency.yaml
│   ├── http_errors.yaml
│   ├── human_name_in_whois.yaml
│   ├── internal_host.yaml
│   ├── multiple_malicious.yaml
│   ├── multiple_malicious_affiliate.yaml
│   ├── multiple_malicious_cohost.yaml
│   ├── name_only_from_pasteleak_site.yaml
│   ├── open_port_version.yaml
│   ├── outlier_cloud.yaml
│   ├── outlier_country.yaml
│   ├── outlier_email.yaml
│   ├── outlier_hostname.yaml
│   ├── outlier_ipaddress.yaml
│   ├── outlier_registrar.yaml
│   ├── outlier_webserver.yaml
│   ├── remote_desktop_exposed.yaml
│   ├── root_path_needs_auth.yaml
│   ├── stale_host.yaml
│   ├── strong_affiliate_certs.yaml
│   ├── strong_similardomain_crossref.yaml
│   ├── template.yaml
│   ├── vulnerability_critical.yaml
│   ├── vulnerability_high.yaml
│   └── vulnerability_mediumlow.yaml
├── docker-compose-dev.yml
├── docker-compose-full.yml
├── docker-compose.yml
├── docs/
│   ├── Makefile
│   ├── conf.py
│   ├── index.rst
│   ├── make.bat
│   └── spiderfoot.rst
├── generate-certificate
├── modules/
│   ├── __init__.py
│   ├── sfp__stor_db.py
│   ├── sfp__stor_stdout.py
│   ├── sfp_abstractapi.py
│   ├── sfp_abusech.py
│   ├── sfp_abuseipdb.py
│   ├── sfp_abusix.py
│   ├── sfp_accounts.py
│   ├── sfp_adblock.py
│   ├── sfp_adguard_dns.py
│   ├── sfp_ahmia.py
│   ├── sfp_alienvault.py
│   ├── sfp_alienvaultiprep.py
│   ├── sfp_apple_itunes.py
│   ├── sfp_archiveorg.py
│   ├── sfp_arin.py
│   ├── sfp_azureblobstorage.py
│   ├── sfp_base64.py
│   ├── sfp_bgpview.py
│   ├── sfp_binaryedge.py
│   ├── sfp_bingsearch.py
│   ├── sfp_bingsharedip.py
│   ├── sfp_binstring.py
│   ├── sfp_bitcoin.py
│   ├── sfp_bitcoinabuse.py
│   ├── sfp_bitcoinwhoswho.py
│   ├── sfp_blockchain.py
│   ├── sfp_blocklistde.py
│   ├── sfp_botscout.py
│   ├── sfp_botvrij.py
│   ├── sfp_builtwith.py
│   ├── sfp_c99.py
│   ├── sfp_callername.py
│   ├── sfp_censys.py
│   ├── sfp_certspotter.py
│   ├── sfp_cinsscore.py
│   ├── sfp_circllu.py
│   ├── sfp_citadel.py
│   ├── sfp_cleanbrowsing.py
│   ├── sfp_cleantalk.py
│   ├── sfp_clearbit.py
│   ├── sfp_cloudflaredns.py
│   ├── sfp_coinblocker.py
│   ├── sfp_commoncrawl.py
│   ├── sfp_comodo.py
│   ├── sfp_company.py
│   ├── sfp_cookie.py
│   ├── sfp_countryname.py
│   ├── sfp_creditcard.py
│   ├── sfp_crobat_api.py
│   ├── sfp_crossref.py
│   ├── sfp_crt.py
│   ├── sfp_crxcavator.py
│   ├── sfp_customfeed.py
│   ├── sfp_cybercrimetracker.py
│   ├── sfp_debounce.py
│   ├── sfp_dehashed.py
│   ├── sfp_digitaloceanspace.py
│   ├── sfp_dns_for_family.py
│   ├── sfp_dnsbrute.py
│   ├── sfp_dnscommonsrv.py
│   ├── sfp_dnsdb.py
│   ├── sfp_dnsdumpster.py
│   ├── sfp_dnsgrep.py
│   ├── sfp_dnsneighbor.py
│   ├── sfp_dnsraw.py
│   ├── sfp_dnsresolve.py
│   ├── sfp_dnszonexfer.py
│   ├── sfp_dronebl.py
│   ├── sfp_duckduckgo.py
│   ├── sfp_email.py
│   ├── sfp_emailcrawlr.py
│   ├── sfp_emailformat.py
│   ├── sfp_emailrep.py
│   ├── sfp_emergingthreats.py
│   ├── sfp_errors.py
│   ├── sfp_ethereum.py
│   ├── sfp_etherscan.py
│   ├── sfp_filemeta.py
│   ├── sfp_flickr.py
│   ├── sfp_focsec.py
│   ├── sfp_fortinet.py
│   ├── sfp_fraudguard.py
│   ├── sfp_fsecure_riddler.py
│   ├── sfp_fullcontact.py
│   ├── sfp_fullhunt.py
│   ├── sfp_github.py
│   ├── sfp_gleif.py
│   ├── sfp_google_tag_manager.py
│   ├── sfp_googlemaps.py
│   ├── sfp_googleobjectstorage.py
│   ├── sfp_googlesafebrowsing.py
│   ├── sfp_googlesearch.py
│   ├── sfp_gravatar.py
│   ├── sfp_grayhatwarfare.py
│   ├── sfp_greensnow.py
│   ├── sfp_grep_app.py
│   ├── sfp_greynoise.py
│   ├── sfp_greynoise_community.py
│   ├── sfp_h1nobbdde.py
│   ├── sfp_hackertarget.py
│   ├── sfp_hashes.py
│   ├── sfp_haveibeenpwned.py
│   ├── sfp_honeypot.py
│   ├── sfp_hosting.py
│   ├── sfp_hostio.py
│   ├── sfp_hunter.py
│   ├── sfp_hybrid_analysis.py
│   ├── sfp_iban.py
│   ├── sfp_iknowwhatyoudownload.py
│   ├── sfp_intelx.py
│   ├── sfp_intfiles.py
│   ├── sfp_ipapico.py
│   ├── sfp_ipapicom.py
│   ├── sfp_ipinfo.py
│   ├── sfp_ipqualityscore.py
│   ├── sfp_ipregistry.py
│   ├── sfp_ipstack.py
│   ├── sfp_isc.py
│   ├── sfp_jsonwhoiscom.py
│   ├── sfp_junkfiles.py
│   ├── sfp_keybase.py
│   ├── sfp_koodous.py
│   ├── sfp_leakix.py
│   ├── sfp_maltiverse.py
│   ├── sfp_malwarepatrol.py
│   ├── sfp_metadefender.py
│   ├── sfp_mnemonic.py
│   ├── sfp_multiproxy.py
│   ├── sfp_myspace.py
│   ├── sfp_nameapi.py
│   ├── sfp_names.py
│   ├── sfp_networksdb.py
│   ├── sfp_neutrinoapi.py
│   ├── sfp_numverify.py
│   ├── sfp_onioncity.py
│   ├── sfp_onionsearchengine.py
│   ├── sfp_onyphe.py
│   ├── sfp_openbugbounty.py
│   ├── sfp_opencorporates.py
│   ├── sfp_opendns.py
│   ├── sfp_opennic.py
│   ├── sfp_openphish.py
│   ├── sfp_openstreetmap.py
│   ├── sfp_pageinfo.py
│   ├── sfp_pastebin.py
│   ├── sfp_pgp.py
│   ├── sfp_phishstats.py
│   ├── sfp_phishtank.py
│   ├── sfp_phone.py
│   ├── sfp_portscan_tcp.py
│   ├── sfp_projectdiscovery.py
│   ├── sfp_psbdmp.py
│   ├── sfp_pulsedive.py
│   ├── sfp_punkspider.py
│   ├── sfp_quad9.py
│   ├── sfp_reversewhois.py
│   ├── sfp_ripe.py
│   ├── sfp_riskiq.py
│   ├── sfp_robtex.py
│   ├── sfp_s3bucket.py
│   ├── sfp_searchcode.py
│   ├── sfp_securitytrails.py
│   ├── sfp_seon.py
│   ├── sfp_shodan.py
│   ├── sfp_similar.py
│   ├── sfp_skymem.py
│   ├── sfp_slideshare.py
│   ├── sfp_snov.py
│   ├── sfp_social.py
│   ├── sfp_sociallinks.py
│   ├── sfp_socialprofiles.py
│   ├── sfp_sorbs.py
│   ├── sfp_spamcop.py
│   ├── sfp_spamhaus.py
│   ├── sfp_spider.py
│   ├── sfp_spur.py
│   ├── sfp_spyonweb.py
│   ├── sfp_sslcert.py
│   ├── sfp_stackoverflow.py
│   ├── sfp_stevenblack_hosts.py
│   ├── sfp_strangeheaders.py
│   ├── sfp_subdomain_takeover.py
│   ├── sfp_sublist3r.py
│   ├── sfp_surbl.py
│   ├── sfp_talosintel.py
│   ├── sfp_template.py
│   ├── sfp_textmagic.py
│   ├── sfp_threatcrowd.py
│   ├── sfp_threatfox.py
│   ├── sfp_threatjammer.py
│   ├── sfp_threatminer.py
│   ├── sfp_tldsearch.py
│   ├── sfp_tool_cmseek.py
│   ├── sfp_tool_dnstwist.py
│   ├── sfp_tool_nbtscan.py
│   ├── sfp_tool_nmap.py
│   ├── sfp_tool_nuclei.py
│   ├── sfp_tool_onesixtyone.py
│   ├── sfp_tool_retirejs.py
│   ├── sfp_tool_snallygaster.py
│   ├── sfp_tool_testsslsh.py
│   ├── sfp_tool_trufflehog.py
│   ├── sfp_tool_wafw00f.py
│   ├── sfp_tool_wappalyzer.py
│   ├── sfp_tool_whatweb.py
│   ├── sfp_torch.py
│   ├── sfp_torexits.py
│   ├── sfp_trashpanda.py
│   ├── sfp_trumail.py
│   ├── sfp_twilio.py
│   ├── sfp_twitter.py
│   ├── sfp_uceprotect.py
│   ├── sfp_urlscan.py
│   ├── sfp_venmo.py
│   ├── sfp_viewdns.py
│   ├── sfp_virustotal.py
│   ├── sfp_voipbl.py
│   ├── sfp_vxvault.py
│   ├── sfp_webanalytics.py
│   ├── sfp_webframework.py
│   ├── sfp_webserver.py
│   ├── sfp_whatcms.py
│   ├── sfp_whois.py
│   ├── sfp_whoisology.py
│   ├── sfp_whoxy.py
│   ├── sfp_wigle.py
│   ├── sfp_wikileaks.py
│   ├── sfp_wikipediaedits.py
│   ├── sfp_xforce.py
│   ├── sfp_yandexdns.py
│   ├── sfp_zetalytics.py
│   ├── sfp_zonefiles.py
│   └── sfp_zoneh.py
├── requirements.txt
├── setup.cfg
├── sf.py
├── sfcli.py
├── sflib.py
├── sfscan.py
├── sfwebui.py
├── spiderfoot/
│   ├── __init__.py
│   ├── __version__.py
│   ├── correlation.py
│   ├── db.py
│   ├── dicts/
│   │   ├── __init__.py
│   │   ├── generic-usernames.txt
│   │   ├── ispell/
│   │   │   ├── LICENSE
│   │   │   ├── __init__.py
│   │   │   ├── english.dict
│   │   │   ├── french.dict
│   │   │   ├── german.dict
│   │   │   ├── names.dict
│   │   │   └── spanish.dict
│   │   ├── subdomains-10000.txt
│   │   └── subdomains.txt
│   ├── event.py
│   ├── helpers.py
│   ├── logger.py
│   ├── plugin.py
│   ├── static/
│   │   ├── css/
│   │   │   ├── dark.css
│   │   │   └── spiderfoot.css
│   │   ├── js/
│   │   │   ├── spiderfoot.js
│   │   │   ├── spiderfoot.newscan.js
│   │   │   ├── spiderfoot.opts.js
│   │   │   ├── spiderfoot.scanlist.js
│   │   │   └── viz.js
│   │   └── package.json
│   ├── target.py
│   ├── templates/
│   │   ├── FOOTER.tmpl
│   │   ├── HEADER.tmpl
│   │   ├── error.tmpl
│   │   ├── newscan.tmpl
│   │   ├── opts.tmpl
│   │   ├── scaninfo.tmpl
│   │   └── scanlist.tmpl
│   └── threadpool.py
└── test/
    ├── README.md
    ├── __init__.py
    ├── acceptance/
    │   ├── requirements.txt
    │   ├── run
    │   └── scan.robot
    ├── bandit
    ├── conftest.py
    ├── integration/
    │   ├── __init__.py
    │   ├── modules/
    │   │   ├── __init__.py
    │   │   ├── test_sfp__stor_db.py
    │   │   ├── test_sfp__stor_stdout.py
    │   │   ├── test_sfp_abstractapi.py
    │   │   ├── test_sfp_abusech.py
    │   │   ├── test_sfp_abuseipdb.py
    │   │   ├── test_sfp_abusix.py
    │   │   ├── test_sfp_accounts.py
    │   │   ├── test_sfp_adblock.py
    │   │   ├── test_sfp_adguard_dns.py
    │   │   ├── test_sfp_ahmia.py
    │   │   ├── test_sfp_alienvault.py
    │   │   ├── test_sfp_alienvaultiprep.py
    │   │   ├── test_sfp_apple_itunes.py
    │   │   ├── test_sfp_archiveorg.py
    │   │   ├── test_sfp_arin.py
    │   │   ├── test_sfp_azureblobstorage.py
    │   │   ├── test_sfp_bgpview.py
    │   │   ├── test_sfp_binaryedge.py
    │   │   ├── test_sfp_bingsearch.py
    │   │   ├── test_sfp_bingsharedip.py
    │   │   ├── test_sfp_bitcoinabuse.py
    │   │   ├── test_sfp_bitcoinwhoswho.py
    │   │   ├── test_sfp_blockchain.py
    │   │   ├── test_sfp_blocklistde.py
    │   │   ├── test_sfp_botscout.py
    │   │   ├── test_sfp_botvrij.py
    │   │   ├── test_sfp_builtwith.py
    │   │   ├── test_sfp_c99.py
    │   │   ├── test_sfp_callername.py
    │   │   ├── test_sfp_censys.py
    │   │   ├── test_sfp_certspotter.py
    │   │   ├── test_sfp_cinsscore.py
    │   │   ├── test_sfp_circllu.py
    │   │   ├── test_sfp_citadel.py
    │   │   ├── test_sfp_cleanbrowsing.py
    │   │   ├── test_sfp_cleantalk.py
    │   │   ├── test_sfp_clearbit.py
    │   │   ├── test_sfp_cloudflaredns.py
    │   │   ├── test_sfp_coinblocker.py
    │   │   ├── test_sfp_commoncrawl.py
    │   │   ├── test_sfp_comodo.py
    │   │   ├── test_sfp_crobat_api.py
    │   │   ├── test_sfp_crossref.py
    │   │   ├── test_sfp_crt.py
    │   │   ├── test_sfp_crxcavator.py
    │   │   ├── test_sfp_customfeed.py
    │   │   ├── test_sfp_cybercrimetracker.py
    │   │   ├── test_sfp_debounce.py
    │   │   ├── test_sfp_dehashed.py
    │   │   ├── test_sfp_digitaloceanspace.py
    │   │   ├── test_sfp_dns_for_family.py
    │   │   ├── test_sfp_dnsbrute.py
    │   │   ├── test_sfp_dnscommonsrv.py
    │   │   ├── test_sfp_dnsdb.py
    │   │   ├── test_sfp_dnsdumpster.py
    │   │   ├── test_sfp_dnsgrep.py
    │   │   ├── test_sfp_dnsneighbor.py
    │   │   ├── test_sfp_dnsraw.py
    │   │   ├── test_sfp_dnsresolve.py
    │   │   ├── test_sfp_dnszonexfer.py
    │   │   ├── test_sfp_dronebl.py
    │   │   ├── test_sfp_duckduckgo.py
    │   │   ├── test_sfp_email.py
    │   │   ├── test_sfp_emailcrawlr.py
    │   │   ├── test_sfp_emailformat.py
    │   │   ├── test_sfp_emailrep.py
    │   │   ├── test_sfp_emergingthreats.py
    │   │   ├── test_sfp_etherscan.py
    │   │   ├── test_sfp_filemeta.py
    │   │   ├── test_sfp_flickr.py
    │   │   ├── test_sfp_focsec.py
    │   │   ├── test_sfp_fortinet.py
    │   │   ├── test_sfp_fraudguard.py
    │   │   ├── test_sfp_fsecure_riddler.py
    │   │   ├── test_sfp_fullcontact.py
    │   │   ├── test_sfp_fullhunt.py
    │   │   ├── test_sfp_github.py
    │   │   ├── test_sfp_gleif.py
    │   │   ├── test_sfp_google_tag_manager.py
    │   │   ├── test_sfp_googlemaps.py
    │   │   ├── test_sfp_googleobjectstorage.py
    │   │   ├── test_sfp_googlesafebrowsing.py
    │   │   ├── test_sfp_googlesearch.py
    │   │   ├── test_sfp_gravatar.py
    │   │   ├── test_sfp_grayhatwarfare.py
    │   │   ├── test_sfp_greensnow.py
    │   │   ├── test_sfp_grep_app.py
    │   │   ├── test_sfp_greynoise.py
    │   │   ├── test_sfp_h1nobbdde.py
    │   │   ├── test_sfp_hackertarget.py
    │   │   ├── test_sfp_haveibeenpwned.py
    │   │   ├── test_sfp_honeypot.py
    │   │   ├── test_sfp_hosting.py
    │   │   ├── test_sfp_hostio.py
    │   │   ├── test_sfp_hunter.py
    │   │   ├── test_sfp_hybrid_analysis.py
    │   │   ├── test_sfp_iknowwhatyoudownload.py
    │   │   ├── test_sfp_intelx.py
    │   │   ├── test_sfp_ipapico.py
    │   │   ├── test_sfp_ipapicom.py
    │   │   ├── test_sfp_ipinfo.py
    │   │   ├── test_sfp_ipqualityscore.py
    │   │   ├── test_sfp_ipregistry.py
    │   │   ├── test_sfp_ipstack.py
    │   │   ├── test_sfp_isc.py
    │   │   ├── test_sfp_jsonwhoiscom.py
    │   │   ├── test_sfp_junkfiles.py
    │   │   ├── test_sfp_keybase.py
    │   │   ├── test_sfp_koodous.py
    │   │   ├── test_sfp_leakix.py
    │   │   ├── test_sfp_maltiverse.py
    │   │   ├── test_sfp_malwarepatrol.py
    │   │   ├── test_sfp_metadefender.py
    │   │   ├── test_sfp_mnemonic.py
    │   │   ├── test_sfp_multiproxy.py
    │   │   ├── test_sfp_myspace.py
    │   │   ├── test_sfp_nameapi.py
    │   │   ├── test_sfp_networksdb.py
    │   │   ├── test_sfp_neutrinoapi.py
    │   │   ├── test_sfp_numverify.py
    │   │   ├── test_sfp_onioncity.py
    │   │   ├── test_sfp_onionsearchengine.py
    │   │   ├── test_sfp_onyphe.py
    │   │   ├── test_sfp_openbugbounty.py
    │   │   ├── test_sfp_opencorporates.py
    │   │   ├── test_sfp_opendns.py
    │   │   ├── test_sfp_opennic.py
    │   │   ├── test_sfp_openphish.py
    │   │   ├── test_sfp_openstreetmap.py
    │   │   ├── test_sfp_pageinfo.py
    │   │   ├── test_sfp_pastebin.py
    │   │   ├── test_sfp_pgp.py
    │   │   ├── test_sfp_phishstats.py
    │   │   ├── test_sfp_phishtank.py
    │   │   ├── test_sfp_portscan_tcp.py
    │   │   ├── test_sfp_projectdiscovery.py
    │   │   ├── test_sfp_psbdmp.py
    │   │   ├── test_sfp_pulsedive.py
    │   │   ├── test_sfp_punkspider.py
    │   │   ├── test_sfp_quad9.py
    │   │   ├── test_sfp_reversewhois.py
    │   │   ├── test_sfp_ripe.py
    │   │   ├── test_sfp_riskiq.py
    │   │   ├── test_sfp_robtex.py
    │   │   ├── test_sfp_s3bucket.py
    │   │   ├── test_sfp_searchcode.py
    │   │   ├── test_sfp_securitytrails.py
    │   │   ├── test_sfp_seon.py
    │   │   ├── test_sfp_shodan.py
    │   │   ├── test_sfp_similar.py
    │   │   ├── test_sfp_skymem.py
    │   │   ├── test_sfp_slideshare.py
    │   │   ├── test_sfp_snov.py
    │   │   ├── test_sfp_sociallinks.py
    │   │   ├── test_sfp_socialprofiles.py
    │   │   ├── test_sfp_sorbs.py
    │   │   ├── test_sfp_spamcop.py
    │   │   ├── test_sfp_spamhaus.py
    │   │   ├── test_sfp_spider.py
    │   │   ├── test_sfp_spur.py
    │   │   ├── test_sfp_spyonweb.py
    │   │   ├── test_sfp_sslcert.py
    │   │   ├── test_sfp_stackoverflow.py
    │   │   ├── test_sfp_stevenblack_hosts.py
    │   │   ├── test_sfp_subdomain_takeover.py
    │   │   ├── test_sfp_sublist3r.py
    │   │   ├── test_sfp_surbl.py
    │   │   ├── test_sfp_talosintel.py
    │   │   ├── test_sfp_textmagic.py
    │   │   ├── test_sfp_threatcrowd.py
    │   │   ├── test_sfp_threatfox.py
    │   │   ├── test_sfp_threatminer.py
    │   │   ├── test_sfp_tldsearch.py
    │   │   ├── test_sfp_torch.py
    │   │   ├── test_sfp_torexits.py
    │   │   ├── test_sfp_trashpanda.py
    │   │   ├── test_sfp_trumail.py
    │   │   ├── test_sfp_twilio.py
    │   │   ├── test_sfp_twitter.py
    │   │   ├── test_sfp_uceprotect.py
    │   │   ├── test_sfp_urlscan.py
    │   │   ├── test_sfp_venmo.py
    │   │   ├── test_sfp_viewdns.py
    │   │   ├── test_sfp_virustotal.py
    │   │   ├── test_sfp_voipbl.py
    │   │   ├── test_sfp_vxvault.py
    │   │   ├── test_sfp_webserver.py
    │   │   ├── test_sfp_whatcms.py
    │   │   ├── test_sfp_whois.py
    │   │   ├── test_sfp_whoisology.py
    │   │   ├── test_sfp_whoxy.py
    │   │   ├── test_sfp_wigle.py
    │   │   ├── test_sfp_wikileaks.py
    │   │   ├── test_sfp_wikipediaedits.py
    │   │   ├── test_sfp_xforce.py
    │   │   ├── test_sfp_yandexdns.py
    │   │   ├── test_sfp_zetalytics.py
    │   │   └── test_sfp_zoneh.py
    │   ├── test_sf.py
    │   ├── test_sfcli.py
    │   └── test_sfwebui.py
    ├── requirements.txt
    ├── run
    ├── unit/
    │   ├── __init__.py
    │   ├── modules/
    │   │   ├── __init__.py
    │   │   ├── test_sfp__stor_db.py
    │   │   ├── test_sfp__stor_stdout.py
    │   │   ├── test_sfp_abstractapi.py
    │   │   ├── test_sfp_abusech.py
    │   │   ├── test_sfp_abuseipdb.py
    │   │   ├── test_sfp_abusix.py
    │   │   ├── test_sfp_accounts.py
    │   │   ├── test_sfp_adblock.py
    │   │   ├── test_sfp_adguard_dns.py
    │   │   ├── test_sfp_ahmia.py
    │   │   ├── test_sfp_alienvault.py
    │   │   ├── test_sfp_alienvaultiprep.py
    │   │   ├── test_sfp_apple_itunes.py
    │   │   ├── test_sfp_archiveorg.py
    │   │   ├── test_sfp_arin.py
    │   │   ├── test_sfp_azureblobstorage.py
    │   │   ├── test_sfp_base64.py
    │   │   ├── test_sfp_bgpview.py
    │   │   ├── test_sfp_binaryedge.py
    │   │   ├── test_sfp_bingsearch.py
    │   │   ├── test_sfp_bingsharedip.py
    │   │   ├── test_sfp_binstring.py
    │   │   ├── test_sfp_bitcoin.py
    │   │   ├── test_sfp_bitcoinabuse.py
    │   │   ├── test_sfp_bitcoinwhoswho.py
    │   │   ├── test_sfp_blockchain.py
    │   │   ├── test_sfp_blocklistde.py
    │   │   ├── test_sfp_botscout.py
    │   │   ├── test_sfp_botvrij.py
    │   │   ├── test_sfp_builtwith.py
    │   │   ├── test_sfp_c99.py
    │   │   ├── test_sfp_callername.py
    │   │   ├── test_sfp_censys.py
    │   │   ├── test_sfp_certspotter.py
    │   │   ├── test_sfp_cinsscore.py
    │   │   ├── test_sfp_circllu.py
    │   │   ├── test_sfp_citadel.py
    │   │   ├── test_sfp_cleanbrowsing.py
    │   │   ├── test_sfp_cleantalk.py
    │   │   ├── test_sfp_clearbit.py
    │   │   ├── test_sfp_cloudflaredns.py
    │   │   ├── test_sfp_coinblocker.py
    │   │   ├── test_sfp_commoncrawl.py
    │   │   ├── test_sfp_comodo.py
    │   │   ├── test_sfp_company.py
    │   │   ├── test_sfp_cookie.py
    │   │   ├── test_sfp_countryname.py
    │   │   ├── test_sfp_creditcard.py
    │   │   ├── test_sfp_crobat_api.py
    │   │   ├── test_sfp_crossref.py
    │   │   ├── test_sfp_crt.py
    │   │   ├── test_sfp_crxcavator.py
    │   │   ├── test_sfp_customfeed.py
    │   │   ├── test_sfp_cybercrimetracker.py
    │   │   ├── test_sfp_debounce.py
    │   │   ├── test_sfp_dehashed.py
    │   │   ├── test_sfp_digitaloceanspace.py
    │   │   ├── test_sfp_dns_for_family.py
    │   │   ├── test_sfp_dnsbrute.py
    │   │   ├── test_sfp_dnscommonsrv.py
    │   │   ├── test_sfp_dnsdb.py
    │   │   ├── test_sfp_dnsdumpster.py
    │   │   ├── test_sfp_dnsgrep.py
    │   │   ├── test_sfp_dnsneighbor.py
    │   │   ├── test_sfp_dnsraw.py
    │   │   ├── test_sfp_dnsresolve.py
    │   │   ├── test_sfp_dnszonexfer.py
    │   │   ├── test_sfp_dronebl.py
    │   │   ├── test_sfp_duckduckgo.py
    │   │   ├── test_sfp_email.py
    │   │   ├── test_sfp_emailcrawlr.py
    │   │   ├── test_sfp_emailformat.py
    │   │   ├── test_sfp_emailrep.py
    │   │   ├── test_sfp_emergingthreats.py
    │   │   ├── test_sfp_errors.py
    │   │   ├── test_sfp_ethereum.py
    │   │   ├── test_sfp_etherscan.py
    │   │   ├── test_sfp_filemeta.py
    │   │   ├── test_sfp_flickr.py
    │   │   ├── test_sfp_focsec.py
    │   │   ├── test_sfp_fortinet.py
    │   │   ├── test_sfp_fraudguard.py
    │   │   ├── test_sfp_fsecure_riddler.py
    │   │   ├── test_sfp_fullcontact.py
    │   │   ├── test_sfp_fullhunt.py
    │   │   ├── test_sfp_github.py
    │   │   ├── test_sfp_gleif.py
    │   │   ├── test_sfp_google_tag_manager.py
    │   │   ├── test_sfp_googlemaps.py
    │   │   ├── test_sfp_googleobjectstorage.py
    │   │   ├── test_sfp_googlesafebrowsing.py
    │   │   ├── test_sfp_googlesearch.py
    │   │   ├── test_sfp_gravatar.py
    │   │   ├── test_sfp_grayhatwarfare.py
    │   │   ├── test_sfp_greensnow.py
    │   │   ├── test_sfp_grep_app.py
    │   │   ├── test_sfp_greynoise.py
    │   │   ├── test_sfp_h1nobbdde.py
    │   │   ├── test_sfp_hackertarget.py
    │   │   ├── test_sfp_hashes.py
    │   │   ├── test_sfp_haveibeenpwned.py
    │   │   ├── test_sfp_honeypot.py
    │   │   ├── test_sfp_hosting.py
    │   │   ├── test_sfp_hostio.py
    │   │   ├── test_sfp_hunter.py
    │   │   ├── test_sfp_hybrid_analysis.py
    │   │   ├── test_sfp_iban.py
    │   │   ├── test_sfp_iknowwhatyoudownload.py
    │   │   ├── test_sfp_intelx.py
    │   │   ├── test_sfp_intfiles.py
    │   │   ├── test_sfp_ipapico.py
    │   │   ├── test_sfp_ipapicom.py
    │   │   ├── test_sfp_ipinfo.py
    │   │   ├── test_sfp_ipqualityscore.py
    │   │   ├── test_sfp_ipregistry.py
    │   │   ├── test_sfp_ipstack.py
    │   │   ├── test_sfp_isc.py
    │   │   ├── test_sfp_jsonwhoiscom.py
    │   │   ├── test_sfp_junkfiles.py
    │   │   ├── test_sfp_keybase.py
    │   │   ├── test_sfp_koodous.py
    │   │   ├── test_sfp_leakix.py
    │   │   ├── test_sfp_maltiverse.py
    │   │   ├── test_sfp_malwarepatrol.py
    │   │   ├── test_sfp_metadefender.py
    │   │   ├── test_sfp_mnemonic.py
    │   │   ├── test_sfp_multiproxy.py
    │   │   ├── test_sfp_myspace.py
    │   │   ├── test_sfp_nameapi.py
    │   │   ├── test_sfp_names.py
    │   │   ├── test_sfp_networksdb.py
    │   │   ├── test_sfp_neutrinoapi.py
    │   │   ├── test_sfp_numverify.py
    │   │   ├── test_sfp_onioncity.py
    │   │   ├── test_sfp_onionsearchengine.py
    │   │   ├── test_sfp_onyphe.py
    │   │   ├── test_sfp_openbugbounty.py
    │   │   ├── test_sfp_opencorporates.py
    │   │   ├── test_sfp_opendns.py
    │   │   ├── test_sfp_opennic.py
    │   │   ├── test_sfp_openphish.py
    │   │   ├── test_sfp_openstreetmap.py
    │   │   ├── test_sfp_pageinfo.py
    │   │   ├── test_sfp_pastebin.py
    │   │   ├── test_sfp_pgp.py
    │   │   ├── test_sfp_phishstats.py
    │   │   ├── test_sfp_phishtank.py
    │   │   ├── test_sfp_phone.py
    │   │   ├── test_sfp_portscan_tcp.py
    │   │   ├── test_sfp_projectdiscovery.py
    │   │   ├── test_sfp_psbdmp.py
    │   │   ├── test_sfp_pulsedive.py
    │   │   ├── test_sfp_punkspider.py
    │   │   ├── test_sfp_quad9.py
    │   │   ├── test_sfp_reversewhois.py
    │   │   ├── test_sfp_ripe.py
    │   │   ├── test_sfp_riskiq.py
    │   │   ├── test_sfp_robtex.py
    │   │   ├── test_sfp_s3bucket.py
    │   │   ├── test_sfp_searchcode.py
    │   │   ├── test_sfp_securitytrails.py
    │   │   ├── test_sfp_seon.py
    │   │   ├── test_sfp_shodan.py
    │   │   ├── test_sfp_similar.py
    │   │   ├── test_sfp_skymem.py
    │   │   ├── test_sfp_slideshare.py
    │   │   ├── test_sfp_snov.py
    │   │   ├── test_sfp_social.py
    │   │   ├── test_sfp_sociallinks.py
    │   │   ├── test_sfp_socialprofiles.py
    │   │   ├── test_sfp_sorbs.py
    │   │   ├── test_sfp_spamcop.py
    │   │   ├── test_sfp_spamhaus.py
    │   │   ├── test_sfp_spider.py
    │   │   ├── test_sfp_spur.py
    │   │   ├── test_sfp_spyonweb.py
    │   │   ├── test_sfp_sslcert.py
    │   │   ├── test_sfp_stackoverflow.py
    │   │   ├── test_sfp_stevenblack_hosts.py
    │   │   ├── test_sfp_strangeheaders.py
    │   │   ├── test_sfp_subdomain_takeover.py
    │   │   ├── test_sfp_sublist3r.py
    │   │   ├── test_sfp_surbl.py
    │   │   ├── test_sfp_talosintel.py
    │   │   ├── test_sfp_template.py
    │   │   ├── test_sfp_textmagic.py
    │   │   ├── test_sfp_threatcrowd.py
    │   │   ├── test_sfp_threatfox.py
    │   │   ├── test_sfp_threatminer.py
    │   │   ├── test_sfp_tldsearch.py
    │   │   ├── test_sfp_tool_cmseek.py
    │   │   ├── test_sfp_tool_dnstwist.py
    │   │   ├── test_sfp_tool_nbtscan.py
    │   │   ├── test_sfp_tool_nmap.py
    │   │   ├── test_sfp_tool_nuclei.py
    │   │   ├── test_sfp_tool_onesixtyone.py
    │   │   ├── test_sfp_tool_retirejs.py
    │   │   ├── test_sfp_tool_snallygaster.py
    │   │   ├── test_sfp_tool_testsslsh.py
    │   │   ├── test_sfp_tool_trufflehog.py
    │   │   ├── test_sfp_tool_wafw00f.py
    │   │   ├── test_sfp_tool_wappalyzer.py
    │   │   ├── test_sfp_tool_whatweb.py
    │   │   ├── test_sfp_torch.py
    │   │   ├── test_sfp_torexits.py
    │   │   ├── test_sfp_trashpanda.py
    │   │   ├── test_sfp_trumail.py
    │   │   ├── test_sfp_twilio.py
    │   │   ├── test_sfp_twitter.py
    │   │   ├── test_sfp_uceprotect.py
    │   │   ├── test_sfp_urlscan.py
    │   │   ├── test_sfp_venmo.py
    │   │   ├── test_sfp_viewdns.py
    │   │   ├── test_sfp_virustotal.py
    │   │   ├── test_sfp_voipbl.py
    │   │   ├── test_sfp_vxvault.py
    │   │   ├── test_sfp_webanalytics.py
    │   │   ├── test_sfp_webframework.py
    │   │   ├── test_sfp_webserver.py
    │   │   ├── test_sfp_whatcms.py
    │   │   ├── test_sfp_whois.py
    │   │   ├── test_sfp_whoisology.py
    │   │   ├── test_sfp_whoxy.py
    │   │   ├── test_sfp_wigle.py
    │   │   ├── test_sfp_wikileaks.py
    │   │   ├── test_sfp_wikipediaedits.py
    │   │   ├── test_sfp_xforce.py
    │   │   ├── test_sfp_yandexdns.py
    │   │   ├── test_sfp_zetalytics.py
    │   │   ├── test_sfp_zonefiles.py
    │   │   └── test_sfp_zoneh.py
    │   ├── spiderfoot/
    │   │   ├── test_spiderfootcorrelator.py
    │   │   ├── test_spiderfootdb.py
    │   │   ├── test_spiderfootevent.py
    │   │   ├── test_spiderfoothelpers.py
    │   │   ├── test_spiderfootplugin.py
    │   │   ├── test_spiderfoottarget.py
    │   │   └── test_spiderfootthreadpool.py
    │   ├── test_modules.py
    │   ├── test_spiderfoot.py
    │   ├── test_spiderfootcli.py
    │   ├── test_spiderfootscanner.py
    │   └── test_spiderfootwebui.py
    └── update-requirements
Download .txt
Showing preview only (402K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4203 symbols across 695 files)

FILE: modules/sfp__stor_db.py
  class sfp__stor_db (line 17) | class sfp__stor_db(SpiderFootPlugin):
    method setup (line 37) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 46) | def watchedEvents(self):
    method handleEvent (line 50) | def handleEvent(self, sfEvent):

FILE: modules/sfp__stor_stdout.py
  class sfp__stor_stdout (line 18) | class sfp__stor_stdout(SpiderFootPlugin):
    method setup (line 44) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 53) | def watchedEvents(self):
    method output (line 56) | def output(self, event):
    method handleEvent (line 107) | def handleEvent(self, sfEvent):

FILE: modules/sfp_abstractapi.py
  class sfp_abstractapi (line 20) | class sfp_abstractapi(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method parseApiResponse (line 76) | def parseApiResponse(self, res: dict):
    method queryCompanyEnrichment (line 119) | def queryCompanyEnrichment(self, qry):
    method queryPhoneValidation (line 151) | def queryPhoneValidation(self, qry):
    method queryIpGeolocation (line 183) | def queryIpGeolocation(self, qry):
    method handleEvent (line 215) | def handleEvent(self, event):

FILE: modules/sfp_abusech.py
  class sfp_abusech (line 19) | class sfp_abusech(SpiderFootPlugin):
    method setup (line 82) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 91) | def watchedEvents(self):
    method producedEvents (line 103) | def producedEvents(self):
    method queryFeodoTrackerBlacklist (line 114) | def queryFeodoTrackerBlacklist(self, target, targetType):
    method retrieveFeodoTrackerBlacklist (line 133) | def retrieveFeodoTrackerBlacklist(self):
    method parseFeodoTrackerBlacklist (line 159) | def parseFeodoTrackerBlacklist(self, blacklist):
    method querySslBlacklist (line 185) | def querySslBlacklist(self, target, targetType):
    method retrieveSslBlacklist (line 204) | def retrieveSslBlacklist(self):
    method parseSslBlacklist (line 230) | def parseSslBlacklist(self, blacklist):
    method queryUrlHausBlacklist (line 260) | def queryUrlHausBlacklist(self, target, targetType):
    method retrieveUrlHausBlacklist (line 283) | def retrieveUrlHausBlacklist(self):
    method parseUrlHausBlacklist (line 309) | def parseUrlHausBlacklist(self, blacklist):
    method handleEvent (line 342) | def handleEvent(self, event):

FILE: modules/sfp_abuseipdb.py
  class sfp_abuseipdb (line 22) | class sfp_abuseipdb(SpiderFootPlugin):
    method setup (line 74) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 81) | def watchedEvents(self):
    method producedEvents (line 89) | def producedEvents(self):
    method queryBlacklist (line 97) | def queryBlacklist(self):
    method parseBlacklist (line 147) | def parseBlacklist(self, blacklist):
    method queryIpAddress (line 171) | def queryIpAddress(self, ip):
    method queryNetblock (line 225) | def queryNetblock(self, ip):
    method handleEvent (line 278) | def handleEvent(self, event):

FILE: modules/sfp_abusix.py
  class sfp_abusix (line 21) | class sfp_abusix(SpiderFootPlugin):
    method setup (line 97) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 105) | def watchedEvents(self):
    method producedEvents (line 120) | def producedEvents(self):
    method reverseIpAddress (line 138) | def reverseIpAddress(self, ipaddr):
    method reverseIp6Address (line 144) | def reverseIp6Address(self, ipaddr):
    method query (line 150) | def query(self, qaddr):
    method handleEvent (line 175) | def handleEvent(self, event):

FILE: modules/sfp_accounts.py
  class sfp_accounts (line 24) | class sfp_accounts(SpiderFootPlugin):
    method setup (line 63) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 99) | def watchedEvents(self):
    method producedEvents (line 102) | def producedEvents(self):
    method checkSite (line 106) | def checkSite(self, name, site):
    method checkSites (line 165) | def checkSites(self, username, sites=None):
    method generatePermutations (line 209) | def generatePermutations(self, username):
    method handleEvent (line 289) | def handleEvent(self, event):

FILE: modules/sfp_adblock.py
  class sfp_adblock (line 19) | class sfp_adblock(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 74) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method retrieveBlocklist (line 81) | def retrieveBlocklist(self, blocklist_url):
    method setBlocklistRules (line 106) | def setBlocklistRules(self, blocklist):
    method handleEvent (line 124) | def handleEvent(self, event):

FILE: modules/sfp_adguard_dns.py
  class sfp_adguard_dns (line 19) | class sfp_adguard_dns(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 63) | def producedEvents(self):
    method queryDefaultDNS (line 70) | def queryDefaultDNS(self, qaddr):
    method queryFamilyDNS (line 81) | def queryFamilyDNS(self, qaddr):
    method handleEvent (line 92) | def handleEvent(self, event):

FILE: modules/sfp_ahmia.py
  class sfp_ahmia (line 22) | class sfp_ahmia(SpiderFootPlugin):
    method setup (line 66) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 74) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method handleEvent (line 81) | def handleEvent(self, event):

FILE: modules/sfp_alienvault.py
  class sfp_alienvault (line 25) | class sfp_alienvault(SpiderFootPlugin):
    method setup (line 106) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 116) | def watchedEvents(self):
    method producedEvents (line 132) | def producedEvents(self):
    method parseApiResponse (line 148) | def parseApiResponse(self, res: dict):
    method queryReputation (line 174) | def queryReputation(self, qry):
    method queryPassiveDns (line 196) | def queryPassiveDns(self, qry):
    method queryDomainUrlList (line 218) | def queryDomainUrlList(self, qry, page=1, per_page=50):
    method queryHostnameUrlList (line 236) | def queryHostnameUrlList(self, qry, page=1, per_page=50):
    method handleEvent (line 255) | def handleEvent(self, event):

FILE: modules/sfp_alienvaultiprep.py
  class sfp_alienvaultiprep (line 19) | class sfp_alienvaultiprep(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method queryBlacklist (line 90) | def queryBlacklist(self, target, targetType):
    method retrieveBlacklist (line 109) | def retrieveBlacklist(self):
    method parseBlacklist (line 135) | def parseBlacklist(self, blacklist):
    method handleEvent (line 160) | def handleEvent(self, event):

FILE: modules/sfp_apple_itunes.py
  class sfp_apple_itunes (line 22) | class sfp_apple_itunes(SpiderFootPlugin):
    method setup (line 48) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 55) | def watchedEvents(self):
    method producedEvents (line 60) | def producedEvents(self):
    method query (line 69) | def query(self, qry, limit=100):
    method handleEvent (line 102) | def handleEvent(self, event):

FILE: modules/sfp_archiveorg.py
  class sfp_archiveorg (line 20) | class sfp_archiveorg(SpiderFootPlugin):
    method setup (line 82) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 92) | def watchedEvents(self):
    method producedEvents (line 100) | def producedEvents(self):
    method handleEvent (line 108) | def handleEvent(self, event):

FILE: modules/sfp_arin.py
  class sfp_arin (line 19) | class sfp_arin(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method fetchRir (line 77) | def fetchRir(self, url):
    method query (line 86) | def query(self, qtype, value):
    method handleEvent (line 123) | def handleEvent(self, event):

FILE: modules/sfp_azureblobstorage.py
  class sfp_azureblobstorage (line 21) | class sfp_azureblobstorage(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method checkSite (line 73) | def checkSite(self, url):
    method threadSites (line 80) | def threadSites(self, siteList):
    method batchSites (line 112) | def batchSites(self, sites):
    method handleEvent (line 135) | def handleEvent(self, event):

FILE: modules/sfp_base64.py
  class sfp_base64 (line 19) | class sfp_base64(SpiderFootPlugin):
    method setup (line 39) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 47) | def watchedEvents(self):
    method producedEvents (line 51) | def producedEvents(self):
    method handleEvent (line 55) | def handleEvent(self, event):

FILE: modules/sfp_bgpview.py
  class sfp_bgpview (line 19) | class sfp_bgpview(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method queryAsn (line 74) | def queryAsn(self, qry):
    method queryIp (line 102) | def queryIp(self, qry):
    method queryNetblock (line 130) | def queryNetblock(self, qry):
    method handleEvent (line 158) | def handleEvent(self, event):

FILE: modules/sfp_binaryedge.py
  class sfp_binaryedge (line 21) | class sfp_binaryedge(SpiderFootPlugin):
    method setup (line 87) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 98) | def watchedEvents(self):
    method producedEvents (line 107) | def producedEvents(self):
    method query (line 125) | def query(self, qry, querytype, page=1):
    method handleEvent (line 187) | def handleEvent(self, event):

FILE: modules/sfp_bingsearch.py
  class sfp_bingsearch (line 15) | class sfp_bingsearch(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 72) | def producedEvents(self):
    method handleEvent (line 75) | def handleEvent(self, event):

FILE: modules/sfp_bingsharedip.py
  class sfp_bingsharedip (line 18) | class sfp_bingsharedip(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 78) | def watchedEvents(self):
    method producedEvents (line 84) | def producedEvents(self):
    method handleEvent (line 88) | def handleEvent(self, event):

FILE: modules/sfp_binstring.py
  class sfp_binstring (line 18) | class sfp_binstring(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method getStrings (line 65) | def getStrings(self, content):
    method watchedEvents (line 108) | def watchedEvents(self):
    method producedEvents (line 112) | def producedEvents(self):
    method handleEvent (line 116) | def handleEvent(self, event):

FILE: modules/sfp_bitcoin.py
  class sfp_bitcoin (line 21) | class sfp_bitcoin(SpiderFootPlugin):
    method setup (line 36) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 43) | def watchedEvents(self):
    method producedEvents (line 46) | def producedEvents(self):
    method to_bytes (line 49) | def to_bytes(self, n, length):
    method decode_base58 (line 53) | def decode_base58(self, bc, length):
    method check_bc (line 60) | def check_bc(self, bc):
    method handleEvent (line 64) | def handleEvent(self, event):

FILE: modules/sfp_bitcoinabuse.py
  class sfp_bitcoinabuse (line 20) | class sfp_bitcoinabuse(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method queryAddress (line 77) | def queryAddress(self, address: str):
    method parseApiResponse (line 95) | def parseApiResponse(self, res: dict):
    method handleEvent (line 135) | def handleEvent(self, event):

FILE: modules/sfp_bitcoinwhoswho.py
  class sfp_bitcoinwhoswho (line 19) | class sfp_bitcoinwhoswho(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method query (line 74) | def query(self, qry):
    method emit (line 93) | def emit(self, etype, data, pevent, notify=True):
    method generate_events (line 99) | def generate_events(self, data, pevent):
    method handleEvent (line 110) | def handleEvent(self, event):

FILE: modules/sfp_blockchain.py
  class sfp_blockchain (line 19) | class sfp_blockchain(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 59) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method handleEvent (line 69) | def handleEvent(self, event):

FILE: modules/sfp_blocklistde.py
  class sfp_blocklistde (line 18) | class sfp_blocklistde(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 82) | def producedEvents(self):
    method queryBlacklist (line 94) | def queryBlacklist(self, target, targetType):
    method retrieveBlacklist (line 113) | def retrieveBlacklist(self):
    method parseBlacklist (line 139) | def parseBlacklist(self, blacklist):
    method handleEvent (line 163) | def handleEvent(self, event):

FILE: modules/sfp_botscout.py
  class sfp_botscout (line 21) | class sfp_botscout(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 71) | def watchedEvents(self):
    method producedEvents (line 74) | def producedEvents(self):
    method queryIp (line 77) | def queryIp(self, ip):
    method queryEmail (line 94) | def queryEmail(self, email):
    method parseApiResponse (line 111) | def parseApiResponse(self, res: dict):
    method handleEvent (line 136) | def handleEvent(self, event):

FILE: modules/sfp_botvrij.py
  class sfp_botvrij (line 16) | class sfp_botvrij(SpiderFootPlugin):
    method setup (line 50) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 58) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method queryBlacklist (line 75) | def queryBlacklist(self, target):
    method retrieveBlacklist (line 87) | def retrieveBlacklist(self):
    method parseBlacklist (line 113) | def parseBlacklist(self, blacklist):
    method handleEvent (line 140) | def handleEvent(self, event):

FILE: modules/sfp_builtwith.py
  class sfp_builtwith (line 18) | class sfp_builtwith(SpiderFootPlugin):
    method setup (line 70) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 82) | def watchedEvents(self):
    method producedEvents (line 86) | def producedEvents(self):
    method queryRelationships (line 91) | def queryRelationships(self, t):
    method queryDomainInfo (line 109) | def queryDomainInfo(self, t):
    method handleEvent (line 128) | def handleEvent(self, event):

FILE: modules/sfp_c99.py
  class sfp_c99 (line 18) | class sfp_c99(SpiderFootPlugin):
    method setup (line 63) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 71) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method query (line 98) | def query(self, path, queryParam, queryData):
    method emitRawRirData (line 131) | def emitRawRirData(self, data, event):
    method emitPhoneData (line 135) | def emitPhoneData(self, phoneData, event):
    method emitSubDomainData (line 166) | def emitSubDomainData(self, subDomainData, event):
    method emitDomainHistoryData (line 182) | def emitDomainHistoryData(self, domainHistoryData, event):
    method emitIpToSkypeData (line 204) | def emitIpToSkypeData(self, data, event):
    method emitIpToDomainsData (line 226) | def emitIpToDomainsData(self, data, event):
    method emitProxyDetectionData (line 243) | def emitProxyDetectionData(self, data, event):
    method emitGeoIPData (line 256) | def emitGeoIPData(self, data, event):
    method emitSkypeResolverData (line 308) | def emitSkypeResolverData(self, data, event):
    method emitWafDetectorData (line 340) | def emitWafDetectorData(self, data, event):
    method emitHostname (line 353) | def emitHostname(self, data, event):
    method handleEvent (line 389) | def handleEvent(self, event):

FILE: modules/sfp_callername.py
  class sfp_callername (line 19) | class sfp_callername(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method handleEvent (line 72) | def handleEvent(self, event):

FILE: modules/sfp_censys.py
  class sfp_censys (line 26) | class sfp_censys(SpiderFootPlugin):
    method setup (line 81) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 88) | def watchedEvents(self):
    method producedEvents (line 96) | def producedEvents(self):
    method queryHosts (line 111) | def queryHosts(self, qry):
    method queryHostsSearch (line 131) | def queryHostsSearch(self, qry):
    method parseApiResponse (line 155) | def parseApiResponse(self, res: dict):
    method handleEvent (line 201) | def handleEvent(self, event):

FILE: modules/sfp_certspotter.py
  class sfp_certspotter (line 23) | class sfp_certspotter(SpiderFootPlugin):
    method setup (line 68) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 77) | def watchedEvents(self):
    method producedEvents (line 81) | def producedEvents(self):
    method queryIssuances (line 98) | def queryIssuances(self, domain, after=None):
    method handleEvent (line 145) | def handleEvent(self, event):

FILE: modules/sfp_cinsscore.py
  class sfp_cinsscore (line 18) | class sfp_cinsscore(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 72) | def producedEvents(self):
    method query (line 84) | def query(self, qry, targetType):
    method handleEvent (line 125) | def handleEvent(self, event):

FILE: modules/sfp_circllu.py
  class sfp_circllu (line 21) | class sfp_circllu(SpiderFootPlugin):
    method setup (line 82) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 94) | def watchedEvents(self):
    method producedEvents (line 98) | def producedEvents(self):
    method query (line 101) | def query(self, qry, qtype):
    method handleEvent (line 132) | def handleEvent(self, event):

FILE: modules/sfp_citadel.py
  class sfp_citadel (line 22) | class sfp_citadel(SpiderFootPlugin):
    method setup (line 71) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 81) | def watchedEvents(self):
    method producedEvents (line 87) | def producedEvents(self):
    method queryEmail (line 92) | def queryEmail(self, email):
    method handleEvent (line 126) | def handleEvent(self, event):

FILE: modules/sfp_cleanbrowsing.py
  class sfp_cleanbrowsing (line 20) | class sfp_cleanbrowsing(SpiderFootPlugin):
    method setup (line 59) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method queryFamilyDNS (line 83) | def queryFamilyDNS(self, qaddr):
    method queryAdultDNS (line 98) | def queryAdultDNS(self, qaddr):
    method querySecurityDNS (line 113) | def querySecurityDNS(self, qaddr):
    method handleEvent (line 128) | def handleEvent(self, event):

FILE: modules/sfp_cleantalk.py
  class sfp_cleantalk (line 18) | class sfp_cleantalk(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 75) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method query (line 95) | def query(self, qry, targetType):
    method handleEvent (line 139) | def handleEvent(self, event):

FILE: modules/sfp_clearbit.py
  class sfp_clearbit (line 21) | class sfp_clearbit(SpiderFootPlugin):
    method setup (line 66) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 74) | def watchedEvents(self):
    method producedEvents (line 77) | def producedEvents(self):
    method query (line 88) | def query(self, email: str):
    method parseApiResponse (line 112) | def parseApiResponse(self, res: dict):
    method handleEvent (line 158) | def handleEvent(self, event):

FILE: modules/sfp_cloudflaredns.py
  class sfp_cloudflaredns (line 19) | class sfp_cloudflaredns(SpiderFootPlugin):
    method setup (line 50) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 57) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method queryFamilyDNS (line 74) | def queryFamilyDNS(self, qaddr):
    method queryMalwareDNS (line 85) | def queryMalwareDNS(self, qaddr):
    method handleEvent (line 96) | def handleEvent(self, event):

FILE: modules/sfp_coinblocker.py
  class sfp_coinblocker (line 16) | class sfp_coinblocker(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method queryBlocklist (line 81) | def queryBlocklist(self, target):
    method retrieveBlocklist (line 93) | def retrieveBlocklist(self):
    method parseBlocklist (line 120) | def parseBlocklist(self, blocklist):
    method handleEvent (line 149) | def handleEvent(self, event):

FILE: modules/sfp_commoncrawl.py
  class sfp_commoncrawl (line 20) | class sfp_commoncrawl(SpiderFootPlugin):
    method setup (line 59) | def setup(self, sfc, userOpts=dict()):
    method search (line 68) | def search(self, target):
    method getLatestIndexes (line 89) | def getLatestIndexes(self):
    method watchedEvents (line 124) | def watchedEvents(self):
    method producedEvents (line 130) | def producedEvents(self):
    method handleEvent (line 134) | def handleEvent(self, event):

FILE: modules/sfp_comodo.py
  class sfp_comodo (line 19) | class sfp_comodo(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 60) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method query (line 77) | def query(self, qaddr):
    method handleEvent (line 92) | def handleEvent(self, event):

FILE: modules/sfp_company.py
  class sfp_company (line 19) | class sfp_company(SpiderFootPlugin):
    method setup (line 37) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 44) | def watchedEvents(self):
    method producedEvents (line 50) | def producedEvents(self):
    method handleEvent (line 54) | def handleEvent(self, event):

FILE: modules/sfp_cookie.py
  class sfp_cookie (line 18) | class sfp_cookie(SpiderFootPlugin):
    method setup (line 33) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 42) | def watchedEvents(self):
    method producedEvents (line 46) | def producedEvents(self):
    method handleEvent (line 50) | def handleEvent(self, event):

FILE: modules/sfp_countryname.py
  class sfp_countryname (line 22) | class sfp_countryname(SpiderFootPlugin):
    method setup (line 48) | def setup(self, sfc, userOpts=dict()):
    method detectCountryFromPhone (line 58) | def detectCountryFromPhone(self, srcPhoneNumber: str) -> str:
    method detectCountryFromDomainName (line 88) | def detectCountryFromDomainName(self, srcDomain: str) -> str:
    method detectCountryFromIBAN (line 112) | def detectCountryFromIBAN(self, srcIBAN: str) -> str:
    method detectCountryFromData (line 126) | def detectCountryFromData(self, srcData: str) -> list:
    method watchedEvents (line 169) | def watchedEvents(self):
    method producedEvents (line 176) | def producedEvents(self):
    method handleEvent (line 180) | def handleEvent(self, event):

FILE: modules/sfp_creditcard.py
  class sfp_creditcard (line 17) | class sfp_creditcard(SpiderFootPlugin):
    method setup (line 35) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 46) | def watchedEvents(self):
    method producedEvents (line 50) | def producedEvents(self):
    method handleEvent (line 54) | def handleEvent(self, event):

FILE: modules/sfp_crobat_api.py
  class sfp_crobat_api (line 22) | class sfp_crobat_api(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 62) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method queryDomain (line 68) | def queryDomain(self, qry, page=0):
    method parseApiResponse (line 87) | def parseApiResponse(self, res: dict):
    method handleEvent (line 123) | def handleEvent(self, event):

FILE: modules/sfp_crossref.py
  class sfp_crossref (line 21) | class sfp_crossref(SpiderFootPlugin):
    method setup (line 41) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 48) | def watchedEvents(self):
    method producedEvents (line 56) | def producedEvents(self):
    method handleEvent (line 62) | def handleEvent(self, event):

FILE: modules/sfp_crt.py
  class sfp_crt (line 21) | class sfp_crt(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 65) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method queryDomain (line 79) | def queryDomain(self, qry: str):
    method parseApiResponse (line 95) | def parseApiResponse(self, res: dict):
    method handleEvent (line 131) | def handleEvent(self, event):

FILE: modules/sfp_crxcavator.py
  class sfp_crxcavator (line 22) | class sfp_crxcavator(SpiderFootPlugin):
    method setup (line 52) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 59) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method query (line 76) | def query(self, qry):
    method queryExtension (line 104) | def queryExtension(self, extension_id):
    method handleEvent (line 128) | def handleEvent(self, event):

FILE: modules/sfp_customfeed.py
  class sfp_customfeed (line 29) | class sfp_customfeed(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 74) | def watchedEvents(self):
    method producedEvents (line 81) | def producedEvents(self):
    method resourceList (line 87) | def resourceList(self, replaceme_id, target, targetType):
    method lookupItem (line 163) | def lookupItem(self, resourceId, itemType, target):
    method handleEvent (line 174) | def handleEvent(self, event):

FILE: modules/sfp_cybercrimetracker.py
  class sfp_cybercrimetracker (line 16) | class sfp_cybercrimetracker(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 72) | def producedEvents(self):
    method queryBlacklist (line 86) | def queryBlacklist(self, target):
    method retrieveBlacklist (line 98) | def retrieveBlacklist(self):
    method parseBlacklist (line 124) | def parseBlacklist(self, blacklist):
    method handleEvent (line 154) | def handleEvent(self, event):

FILE: modules/sfp_debounce.py
  class sfp_debounce (line 19) | class sfp_debounce(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 58) | def watchedEvents(self):
    method producedEvents (line 63) | def producedEvents(self):
    method queryEmailAddr (line 69) | def queryEmailAddr(self, qry):
    method handleEvent (line 88) | def handleEvent(self, event):

FILE: modules/sfp_dehashed.py
  class sfp_dehashed (line 19) | class sfp_dehashed(SpiderFootPlugin):
    method setup (line 71) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 79) | def watchedEvents(self):
    method producedEvents (line 86) | def producedEvents(self):
    method query (line 96) | def query(self, event, per_page, start):
    method handleEvent (line 142) | def handleEvent(self, event):

FILE: modules/sfp_digitaloceanspace.py
  class sfp_digitaloceanspace (line 21) | class sfp_digitaloceanspace(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method checkSite (line 76) | def checkSite(self, url):
    method threadSites (line 97) | def threadSites(self, siteList):
    method batchSites (line 129) | def batchSites(self, sites):
    method handleEvent (line 153) | def handleEvent(self, event):

FILE: modules/sfp_dns_for_family.py
  class sfp_dns_for_family (line 18) | class sfp_dns_for_family(SpiderFootPlugin):
    method setup (line 48) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 55) | def watchedEvents(self):
    method producedEvents (line 62) | def producedEvents(self):
    method queryAddr (line 69) | def queryAddr(self, qaddr):
    method handleEvent (line 83) | def handleEvent(self, event):

FILE: modules/sfp_dnsbrute.py
  class sfp_dnsbrute (line 22) | class sfp_dnsbrute(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 81) | def watchedEvents(self):
    method producedEvents (line 90) | def producedEvents(self):
    method tryHost (line 93) | def tryHost(self, name):
    method tryHostWrapper (line 102) | def tryHostWrapper(self, hostList, sourceEvent):
    method sendEvent (line 133) | def sendEvent(self, source, result):
    method handleEvent (line 140) | def handleEvent(self, event):

FILE: modules/sfp_dnscommonsrv.py
  class sfp_dnscommonsrv (line 19) | class sfp_dnscommonsrv(SpiderFootPlugin):
    method setup (line 76) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 84) | def watchedEvents(self):
    method producedEvents (line 87) | def producedEvents(self):
    method handleEvent (line 90) | def handleEvent(self, event):

FILE: modules/sfp_dnsdb.py
  class sfp_dnsdb (line 20) | class sfp_dnsdb(SpiderFootPlugin):
    method setup (line 70) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 78) | def watchedEvents(self):
    method producedEvents (line 82) | def producedEvents(self):
    method query (line 95) | def query(self, endpoint, queryType, query):
    method isTooOld (line 141) | def isTooOld(self, lastSeen):
    method handleEvent (line 148) | def handleEvent(self, event):

FILE: modules/sfp_dnsdumpster.py
  class sfp_dnsdumpster (line 21) | class sfp_dnsdumpster(SpiderFootPlugin):
    method setup (line 41) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 47) | def watchedEvents(self):
    method producedEvents (line 50) | def producedEvents(self):
    method query (line 53) | def query(self, domain):
    method sendEvent (line 116) | def sendEvent(self, source, host):
    method handleEvent (line 123) | def handleEvent(self, event):

FILE: modules/sfp_dnsgrep.py
  class sfp_dnsgrep (line 25) | class sfp_dnsgrep(SpiderFootPlugin):
    method setup (line 69) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 77) | def watchedEvents(self):
    method producedEvents (line 81) | def producedEvents(self):
    method query (line 85) | def query(self, qry):
    method handleEvent (line 110) | def handleEvent(self, event):

FILE: modules/sfp_dnsneighbor.py
  class sfp_dnsneighbor (line 19) | class sfp_dnsneighbor(SpiderFootPlugin):
    method setup (line 45) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 62) | def producedEvents(self):
    method handleEvent (line 66) | def handleEvent(self, event):
    method processHost (line 144) | def processHost(self, host, parentEvent, affiliate=None):

FILE: modules/sfp_dnsraw.py
  class sfp_dnsraw (line 23) | class sfp_dnsraw(SpiderFootPlugin):
    method setup (line 46) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 62) | def producedEvents(self):
    method handleEvent (line 68) | def handleEvent(self, event):

FILE: modules/sfp_dnsresolve.py
  class sfp_dnsresolve (line 22) | class sfp_dnsresolve(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method enrichTarget (line 64) | def enrichTarget(self, target):
    method resolveTargets (line 95) | def resolveTargets(self, target, validateReverse: bool) -> list:
    method watchedEvents (line 187) | def watchedEvents(self):
    method producedEvents (line 202) | def producedEvents(self):
    method handleEvent (line 209) | def handleEvent(self, event) -> None:
    method processHost (line 416) | def processHost(self, host, parentEvent, affiliate=None) -> None:
    method processDomain (line 514) | def processDomain(self, domainName, parentEvent, affil=False, host=Non...

FILE: modules/sfp_dnszonexfer.py
  class sfp_dnszonexfer (line 21) | class sfp_dnszonexfer(SpiderFootPlugin):
    method setup (line 41) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 49) | def watchedEvents(self):
    method producedEvents (line 52) | def producedEvents(self):
    method handleEvent (line 55) | def handleEvent(self, event):

FILE: modules/sfp_dronebl.py
  class sfp_dronebl (line 20) | class sfp_dronebl(SpiderFootPlugin):
    method setup (line 82) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 89) | def watchedEvents(self):
    method producedEvents (line 97) | def producedEvents(self):
    method reverseAddr (line 112) | def reverseAddr(self, ipaddr):
    method queryAddr (line 118) | def queryAddr(self, qaddr):
    method handleEvent (line 141) | def handleEvent(self, event):

FILE: modules/sfp_duckduckgo.py
  class sfp_duckduckgo (line 18) | class sfp_duckduckgo(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_email.py
  class sfp_email (line 17) | class sfp_email(SpiderFootPlugin):
    method setup (line 32) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 39) | def watchedEvents(self):
    method producedEvents (line 48) | def producedEvents(self):
    method handleEvent (line 52) | def handleEvent(self, event):

FILE: modules/sfp_emailcrawlr.py
  class sfp_emailcrawlr (line 23) | class sfp_emailcrawlr(SpiderFootPlugin):
    method setup (line 69) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 78) | def watchedEvents(self):
    method producedEvents (line 82) | def producedEvents(self):
    method queryDomain (line 88) | def queryDomain(self, qry):
    method parseApiResponse (line 109) | def parseApiResponse(self, res: dict):
    method handleEvent (line 150) | def handleEvent(self, event):

FILE: modules/sfp_emailformat.py
  class sfp_emailformat (line 21) | class sfp_emailformat(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 58) | def watchedEvents(self):
    method producedEvents (line 61) | def producedEvents(self):
    method handleEvent (line 64) | def handleEvent(self, event):

FILE: modules/sfp_emailrep.py
  class sfp_emailrep (line 19) | class sfp_emailrep(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method query (line 75) | def query(self, qry):
    method handleEvent (line 123) | def handleEvent(self, event):

FILE: modules/sfp_emergingthreats.py
  class sfp_emergingthreats (line 19) | class sfp_emergingthreats(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 69) | def watchedEvents(self):
    method producedEvents (line 77) | def producedEvents(self):
    method query (line 89) | def query(self, qry, targetType):
    method handleEvent (line 130) | def handleEvent(self, event):

FILE: modules/sfp_errors.py
  class sfp_errors (line 30) | class sfp_errors(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_ethereum.py
  class sfp_ethereum (line 19) | class sfp_ethereum(SpiderFootPlugin):
    method setup (line 35) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 43) | def watchedEvents(self):
    method producedEvents (line 49) | def producedEvents(self):
    method handleEvent (line 53) | def handleEvent(self, event):

FILE: modules/sfp_etherscan.py
  class sfp_etherscan (line 20) | class sfp_etherscan(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method query (line 84) | def query(self, qry):
    method handleEvent (line 105) | def handleEvent(self, event):

FILE: modules/sfp_filemeta.py
  class sfp_filemeta (line 28) | class sfp_filemeta(SpiderFootPlugin):
    method setup (line 52) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method handleEvent (line 71) | def handleEvent(self, event):

FILE: modules/sfp_flickr.py
  class sfp_flickr (line 24) | class sfp_flickr(SpiderFootPlugin):
    method setup (line 71) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 79) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method retrieveApiKey (line 88) | def retrieveApiKey(self):
    method query (line 102) | def query(self, qry, api_key, page=1, per_page=200):
    method handleEvent (line 137) | def handleEvent(self, event):

FILE: modules/sfp_focsec.py
  class sfp_focsec (line 19) | class sfp_focsec(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method query (line 80) | def query(self, qry):
    method handleEvent (line 143) | def handleEvent(self, event):

FILE: modules/sfp_fortinet.py
  class sfp_fortinet (line 16) | class sfp_fortinet(SpiderFootPlugin):
    method setup (line 47) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 55) | def watchedEvents(self):
    method producedEvents (line 63) | def producedEvents(self):
    method query (line 71) | def query(self, ip):
    method handleEvent (line 93) | def handleEvent(self, event):

FILE: modules/sfp_fraudguard.py
  class sfp_fraudguard (line 23) | class sfp_fraudguard(SpiderFootPlugin):
    method setup (line 85) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 93) | def watchedEvents(self):
    method producedEvents (line 105) | def producedEvents(self):
    method query (line 114) | def query(self, qry):
    method handleEvent (line 159) | def handleEvent(self, event):

FILE: modules/sfp_fsecure_riddler.py
  class sfp_fsecure_riddler (line 19) | class sfp_fsecure_riddler(SpiderFootPlugin):
    method setup (line 65) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 72) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method login (line 84) | def login(self):
    method query (line 123) | def query(self, qry):
    method handleEvent (line 160) | def handleEvent(self, event):

FILE: modules/sfp_fullcontact.py
  class sfp_fullcontact (line 19) | class sfp_fullcontact(SpiderFootPlugin):
    method setup (line 69) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 77) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method query (line 90) | def query(self, url, data, failcount=0):
    method queryCompany (line 138) | def queryCompany(self, domain):
    method queryPersonByEmail (line 146) | def queryPersonByEmail(self, email):
    method queryPersonByName (line 154) | def queryPersonByName(self, name):
    method handleEvent (line 162) | def handleEvent(self, event):

FILE: modules/sfp_fullhunt.py
  class sfp_fullhunt (line 18) | class sfp_fullhunt(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method queryDomainDetails (line 81) | def queryDomainDetails(self, qry):
    method parseApiResponse (line 103) | def parseApiResponse(self, res: dict):
    method handleEvent (line 139) | def handleEvent(self, event):

FILE: modules/sfp_github.py
  class sfp_github (line 19) | class sfp_github(SpiderFootPlugin):
    method setup (line 50) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 58) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method buildRepoInfo (line 68) | def buildRepoInfo(self, item):
    method handleEvent (line 87) | def handleEvent(self, event):

FILE: modules/sfp_gleif.py
  class sfp_gleif (line 20) | class sfp_gleif(SpiderFootPlugin):
    method setup (line 50) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 57) | def watchedEvents(self):
    method producedEvents (line 60) | def producedEvents(self):
    method searchLegalName (line 63) | def searchLegalName(self, qry):
    method searchAutocompletions (line 107) | def searchAutocompletions(self, qry):
    method retrieveRecord (line 151) | def retrieveRecord(self, lei):
    method handleEvent (line 186) | def handleEvent(self, event):

FILE: modules/sfp_google_tag_manager.py
  class sfp_google_tag_manager (line 21) | class sfp_google_tag_manager(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 62) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method is_valid_hostname (line 74) | def is_valid_hostname(self, hostname: str = None) -> bool:
    method queryGoogleTagId (line 84) | def queryGoogleTagId(self, tag_id: str = None) -> set:
    method handleEvent (line 132) | def handleEvent(self, event):

FILE: modules/sfp_googlemaps.py
  class sfp_googlemaps (line 20) | class sfp_googlemaps(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method query (line 76) | def query(self, address):
    method handleEvent (line 94) | def handleEvent(self, event):

FILE: modules/sfp_googleobjectstorage.py
  class sfp_googleobjectstorage (line 21) | class sfp_googleobjectstorage(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 72) | def producedEvents(self):
    method checkSite (line 75) | def checkSite(self, url):
    method threadSites (line 96) | def threadSites(self, siteList):
    method batchSites (line 128) | def batchSites(self, sites):
    method handleEvent (line 152) | def handleEvent(self, event):

FILE: modules/sfp_googlesafebrowsing.py
  class sfp_googlesafebrowsing (line 19) | class sfp_googlesafebrowsing(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 82) | def producedEvents(self):
    method query (line 92) | def query(self, qry):
    method handleEvent (line 168) | def handleEvent(self, event):

FILE: modules/sfp_googlesearch.py
  class sfp_googlesearch (line 16) | class sfp_googlesearch(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 73) | def watchedEvents(self):
    method producedEvents (line 79) | def producedEvents(self):
    method handleEvent (line 82) | def handleEvent(self, event):

FILE: modules/sfp_gravatar.py
  class sfp_gravatar (line 21) | class sfp_gravatar(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method query (line 76) | def query(self, qry):
    method handleEvent (line 105) | def handleEvent(self, event):

FILE: modules/sfp_grayhatwarfare.py
  class sfp_grayhatwarfare (line 19) | class sfp_grayhatwarfare(SpiderFootPlugin):
    method setup (line 66) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 74) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method query (line 88) | def query(self, keyword, start):
    method handleEvent (line 124) | def handleEvent(self, event):

FILE: modules/sfp_greensnow.py
  class sfp_greensnow (line 18) | class sfp_greensnow(SpiderFootPlugin):
    method setup (line 59) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 75) | def producedEvents(self):
    method query (line 87) | def query(self, qry, targetType):
    method handleEvent (line 128) | def handleEvent(self, event):

FILE: modules/sfp_grep_app.py
  class sfp_grep_app (line 24) | class sfp_grep_app(SpiderFootPlugin):
    method setup (line 59) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method query (line 75) | def query(self, qry, page):
    method handleEvent (line 97) | def handleEvent(self, event):

FILE: modules/sfp_greynoise.py
  class sfp_greynoise (line 23) | class sfp_greynoise(SpiderFootPlugin):
    method setup (line 79) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 90) | def watchedEvents(self):
    method producedEvents (line 94) | def producedEvents(self):
    method queryIP (line 108) | def queryIP(self, qry, qry_type):
    method handleEvent (line 144) | def handleEvent(self, event):

FILE: modules/sfp_greynoise_community.py
  class sfp_greynoise_community (line 22) | class sfp_greynoise_community(SpiderFootPlugin):
    method setup (line 68) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 79) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method queryIP (line 90) | def queryIP(self, qry, qry_type):
    method handleEvent (line 116) | def handleEvent(self, event):

FILE: modules/sfp_h1nobbdde.py
  class sfp_h1nobbdde (line 17) | class sfp_h1nobbdde(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method queryOBB (line 69) | def queryOBB(self, qry):
    method handleEvent (line 90) | def handleEvent(self, event):

FILE: modules/sfp_hackertarget.py
  class sfp_hackertarget (line 26) | class sfp_hackertarget(SpiderFootPlugin):
    method setup (line 73) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 82) | def watchedEvents(self):
    method producedEvents (line 89) | def producedEvents(self):
    method httpHeaders (line 103) | def httpHeaders(self, ip):
    method zoneTransfer (line 146) | def zoneTransfer(self, ip):
    method reverseIpLookup (line 185) | def reverseIpLookup(self, ip):
    method handleEvent (line 222) | def handleEvent(self, event):

FILE: modules/sfp_hashes.py
  class sfp_hashes (line 17) | class sfp_hashes(SpiderFootPlugin):
    method setup (line 36) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 43) | def watchedEvents(self):
    method producedEvents (line 51) | def producedEvents(self):
    method handleEvent (line 55) | def handleEvent(self, event):

FILE: modules/sfp_haveibeenpwned.py
  class sfp_haveibeenpwned (line 19) | class sfp_haveibeenpwned(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 73) | def watchedEvents(self):
    method producedEvents (line 77) | def producedEvents(self):
    method query (line 80) | def query(self, qry):
    method queryPaste (line 122) | def queryPaste(self, qry):
    method handleEvent (line 161) | def handleEvent(self, event):

FILE: modules/sfp_honeypot.py
  class sfp_honeypot (line 19) | class sfp_honeypot(SpiderFootPlugin):
    method setup (line 94) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 101) | def watchedEvents(self):
    method producedEvents (line 109) | def producedEvents(self):
    method reverseAddr (line 122) | def reverseAddr(self, ipaddr):
    method parseDNS (line 126) | def parseDNS(self, addr):
    method queryAddr (line 139) | def queryAddr(self, qaddr, parentEvent):
    method handleEvent (line 187) | def handleEvent(self, event):

FILE: modules/sfp_hosting.py
  class sfp_hosting (line 19) | class sfp_hosting(SpiderFootPlugin):
    method setup (line 40) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 49) | def watchedEvents(self):
    method producedEvents (line 55) | def producedEvents(self):
    method queryAddr (line 58) | def queryAddr(self, qaddr):
    method handleEvent (line 90) | def handleEvent(self, event):

FILE: modules/sfp_hostio.py
  class sfp_hostio (line 17) | class sfp_hostio(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method handle_error_response (line 81) | def handle_error_response(self, qry, res):
    method query (line 96) | def query(self, qry):
    method handleEvent (line 118) | def handleEvent(self, event):

FILE: modules/sfp_hunter.py
  class sfp_hunter (line 20) | class sfp_hunter(SpiderFootPlugin):
    method setup (line 66) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 78) | def watchedEvents(self):
    method producedEvents (line 82) | def producedEvents(self):
    method query (line 85) | def query(self, qry, offset=0, limit=10):
    method handleEvent (line 111) | def handleEvent(self, event):

FILE: modules/sfp_hybrid_analysis.py
  class sfp_hybrid_analysis (line 19) | class sfp_hybrid_analysis(SpiderFootPlugin):
    method setup (line 65) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 73) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method queryDomain (line 79) | def queryDomain(self, qry):
    method queryHost (line 108) | def queryHost(self, qry):
    method queryHash (line 137) | def queryHash(self, qry):
    method parseApiResponse (line 166) | def parseApiResponse(self, res: dict):
    method handleEvent (line 206) | def handleEvent(self, event):

FILE: modules/sfp_iban.py
  class sfp_iban (line 17) | class sfp_iban(SpiderFootPlugin):
    method setup (line 35) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 46) | def watchedEvents(self):
    method producedEvents (line 51) | def producedEvents(self):
    method handleEvent (line 55) | def handleEvent(self, event):

FILE: modules/sfp_iknowwhatyoudownload.py
  class sfp_iknowwhatyoudownload (line 20) | class sfp_iknowwhatyoudownload(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method query (line 76) | def query(self, qry):
    method handleEvent (line 124) | def handleEvent(self, event):

FILE: modules/sfp_intelx.py
  class sfp_intelx (line 21) | class sfp_intelx(SpiderFootPlugin):
    method setup (line 87) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 99) | def watchedEvents(self):
    method producedEvents (line 104) | def producedEvents(self):
    method query (line 109) | def query(self, qry, qtype):
    method handleEvent (line 190) | def handleEvent(self, event):

FILE: modules/sfp_intfiles.py
  class sfp_intfiles (line 16) | class sfp_intfiles(SpiderFootPlugin):
    method setup (line 38) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 47) | def watchedEvents(self):
    method producedEvents (line 53) | def producedEvents(self):
    method handleEvent (line 57) | def handleEvent(self, event):

FILE: modules/sfp_ipapico.py
  class sfp_ipapico (line 20) | class sfp_ipapico(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 59) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method query (line 74) | def query(self, qry):
    method handleEvent (line 94) | def handleEvent(self, event):

FILE: modules/sfp_ipapicom.py
  class sfp_ipapicom (line 20) | class sfp_ipapicom(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 69) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method query (line 84) | def query(self, qry):
    method handleEvent (line 106) | def handleEvent(self, event):

FILE: modules/sfp_ipinfo.py
  class sfp_ipinfo (line 19) | class sfp_ipinfo(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method queryIP (line 77) | def queryIP(self, ip):
    method handleEvent (line 103) | def handleEvent(self, event):

FILE: modules/sfp_ipqualityscore.py
  class sfp_ipqualityscore (line 18) | class sfp_ipqualityscore(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method handle_error_response (line 89) | def handle_error_response(self, qry, res):
    method query (line 104) | def query(self, qry, eventName):
    method getGeoInfo (line 134) | def getGeoInfo(self, data):
    method handleEvent (line 155) | def handleEvent(self, event):

FILE: modules/sfp_ipregistry.py
  class sfp_ipregistry (line 19) | class sfp_ipregistry(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method query (line 70) | def query(self, qry):
    method emit (line 91) | def emit(self, etype, data, pevent):
    method generate_location_events (line 96) | def generate_location_events(self, location, pevent):
    method generate_security_events (line 131) | def generate_security_events(self, security, pevent):
    method generate_events (line 140) | def generate_events(self, data, pevent):
    method handleEvent (line 146) | def handleEvent(self, event):

FILE: modules/sfp_ipstack.py
  class sfp_ipstack (line 19) | class sfp_ipstack(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method handleEvent (line 77) | def handleEvent(self, event):

FILE: modules/sfp_isc.py
  class sfp_isc (line 18) | class sfp_isc(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method query (line 86) | def query(self, ip):
    method handleEvent (line 108) | def handleEvent(self, event):

FILE: modules/sfp_jsonwhoiscom.py
  class sfp_jsonwhoiscom (line 22) | class sfp_jsonwhoiscom(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method queryDomain (line 87) | def queryDomain(self, qry):
    method parseApiResponse (line 108) | def parseApiResponse(self, res: dict):
    method handleEvent (line 154) | def handleEvent(self, event):

FILE: modules/sfp_junkfiles.py
  class sfp_junkfiles (line 18) | class sfp_junkfiles(SpiderFootPlugin):
    method setup (line 50) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 62) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method checkValidity (line 72) | def checkValidity(self, junkUrl):
    method handleEvent (line 86) | def handleEvent(self, event):

FILE: modules/sfp_keybase.py
  class sfp_keybase (line 24) | class sfp_keybase(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method query (line 70) | def query(self, selector: str, qry: str) -> str:
    method handleEvent (line 129) | def handleEvent(self, event) -> None:

FILE: modules/sfp_koodous.py
  class sfp_koodous (line 23) | class sfp_koodous(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 75) | def producedEvents(self):
    method queryPackageName (line 81) | def queryPackageName(self, qry, cursor=''):
    method parseApiResponse (line 101) | def parseApiResponse(self, res: dict):
    method handleEvent (line 141) | def handleEvent(self, event):

FILE: modules/sfp_leakix.py
  class sfp_leakix (line 19) | class sfp_leakix(SpiderFootPlugin):
    method setup (line 66) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 75) | def watchedEvents(self):
    method producedEvents (line 79) | def producedEvents(self):
    method queryApi (line 86) | def queryApi(self, qryType, qry):
    method parseApiResponse (line 103) | def parseApiResponse(self, res: dict):
    method handleEvent (line 135) | def handleEvent(self, event):

FILE: modules/sfp_maltiverse.py
  class sfp_maltiverse (line 22) | class sfp_maltiverse(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 81) | def producedEvents(self):
    method queryIPAddress (line 87) | def queryIPAddress(self, qry):
    method handleEvent (line 121) | def handleEvent(self, event):

FILE: modules/sfp_malwarepatrol.py
  class sfp_malwarepatrol (line 17) | class sfp_malwarepatrol(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 71) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method queryAddr (line 94) | def queryAddr(self, qaddr):
    method handleEvent (line 116) | def handleEvent(self, event):

FILE: modules/sfp_metadefender.py
  class sfp_metadefender (line 19) | class sfp_metadefender(SpiderFootPlugin):
    method setup (line 65) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 74) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method queryDomain (line 89) | def queryDomain(self, qry):
    method queryIp (line 105) | def queryIp(self, qry):
    method parseApiResponse (line 120) | def parseApiResponse(self, res: dict):
    method handleEvent (line 151) | def handleEvent(self, event):

FILE: modules/sfp_mnemonic.py
  class sfp_mnemonic (line 23) | class sfp_mnemonic(SpiderFootPlugin):
    method setup (line 74) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 83) | def watchedEvents(self):
    method producedEvents (line 91) | def producedEvents(self):
    method query (line 101) | def query(self, qry, limit=500, offset=0):
    method handleEvent (line 167) | def handleEvent(self, event):

FILE: modules/sfp_multiproxy.py
  class sfp_multiproxy (line 19) | class sfp_multiproxy(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method queryProxyList (line 88) | def queryProxyList(self, target, targetType):
    method retrieveProxyList (line 108) | def retrieveProxyList(self):
    method parseProxyList (line 134) | def parseProxyList(self, proxy_list):
    method handleEvent (line 158) | def handleEvent(self, event):

FILE: modules/sfp_myspace.py
  class sfp_myspace (line 17) | class sfp_myspace(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 57) | def watchedEvents(self):
    method producedEvents (line 60) | def producedEvents(self):
    method handleEvent (line 63) | def handleEvent(self, event):

FILE: modules/sfp_nameapi.py
  class sfp_nameapi (line 19) | class sfp_nameapi(SpiderFootPlugin):
    method setup (line 59) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method queryEmailAddr (line 77) | def queryEmailAddr(self, qry):
    method handleEvent (line 96) | def handleEvent(self, event):

FILE: modules/sfp_names.py
  class sfp_names (line 18) | class sfp_names(SpiderFootPlugin):
    method setup (line 46) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 62) | def producedEvents(self):
    method handleEvent (line 66) | def handleEvent(self, event):

FILE: modules/sfp_networksdb.py
  class sfp_networksdb (line 23) | class sfp_networksdb(SpiderFootPlugin):
    method setup (line 73) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 83) | def watchedEvents(self):
    method producedEvents (line 87) | def producedEvents(self):
    method queryIpInfo (line 93) | def queryIpInfo(self, qry):
    method queryIpGeo (line 114) | def queryIpGeo(self, qry):
    method queryReverseDns (line 135) | def queryReverseDns(self, qry):
    method queryForwardDns (line 156) | def queryForwardDns(self, qry):
    method queryAsnInfo (line 178) | def queryAsnInfo(self, qry):
    method queryAsnNetworks (line 200) | def queryAsnNetworks(self, qry):
    method parseApiResponse (line 221) | def parseApiResponse(self, res: dict):
    method handleEvent (line 255) | def handleEvent(self, event):

FILE: modules/sfp_neutrinoapi.py
  class sfp_neutrinoapi (line 19) | class sfp_neutrinoapi(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 77) | def watchedEvents(self):
    method producedEvents (line 81) | def producedEvents(self):
    method queryPhoneValidate (line 94) | def queryPhoneValidate(self, qry):
    method queryIpInfo (line 106) | def queryIpInfo(self, qry):
    method queryIpBlocklist (line 118) | def queryIpBlocklist(self, qry):
    method queryHostReputation (line 130) | def queryHostReputation(self, qry):
    method parseApiResponse (line 141) | def parseApiResponse(self, res: dict):
    method handleEvent (line 172) | def handleEvent(self, event):

FILE: modules/sfp_numverify.py
  class sfp_numverify (line 22) | class sfp_numverify(SpiderFootPlugin):
    method setup (line 66) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 75) | def watchedEvents(self):
    method producedEvents (line 79) | def producedEvents(self):
    method query (line 84) | def query(self, qry):
    method handleEvent (line 133) | def handleEvent(self, event):

FILE: modules/sfp_onioncity.py
  class sfp_onioncity (line 19) | class sfp_onioncity(SpiderFootPlugin):
    method setup (line 68) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 77) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method handleEvent (line 87) | def handleEvent(self, event):

FILE: modules/sfp_onionsearchengine.py
  class sfp_onionsearchengine (line 22) | class sfp_onionsearchengine(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 72) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method handleEvent (line 81) | def handleEvent(self, event):

FILE: modules/sfp_onyphe.py
  class sfp_onyphe (line 21) | class sfp_onyphe(SpiderFootPlugin):
    method setup (line 76) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 84) | def watchedEvents(self):
    method producedEvents (line 88) | def producedEvents(self):
    method query (line 104) | def query(self, endpoint, ip, page=1):
    method emitLocationEvent (line 176) | def emitLocationEvent(self, location, eventData, event):
    method emitDomainData (line 184) | def emitDomainData(self, response, eventData, event):
    method isFreshEnough (line 225) | def isFreshEnough(self, result):
    method handleEvent (line 246) | def handleEvent(self, event):

FILE: modules/sfp_openbugbounty.py
  class sfp_openbugbounty (line 17) | class sfp_openbugbounty(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method queryOBB (line 75) | def queryOBB(self, qry):
    method handleEvent (line 97) | def handleEvent(self, event):

FILE: modules/sfp_opencorporates.py
  class sfp_opencorporates (line 20) | class sfp_opencorporates(SpiderFootPlugin):
    method setup (line 63) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 73) | def producedEvents(self):
    method searchCompany (line 76) | def searchCompany(self, qry):
    method retrieveCompanyDetails (line 124) | def retrieveCompanyDetails(self, jurisdiction_code, company_number):
    method extractCompanyDetails (line 156) | def extractCompanyDetails(self, company, sevt):
    method handleEvent (line 198) | def handleEvent(self, event):

FILE: modules/sfp_opendns.py
  class sfp_opendns (line 19) | class sfp_opendns(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 69) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method queryAddr (line 86) | def queryAddr(self, qaddr):
    method handleEvent (line 100) | def handleEvent(self, event):

FILE: modules/sfp_opennic.py
  class sfp_opennic (line 19) | class sfp_opennic(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method queryOpenNIC (line 72) | def queryOpenNIC(self, qaddr):
    method tlds (line 90) | def tlds(self):
    method handleEvent (line 129) | def handleEvent(self, event):

FILE: modules/sfp_openphish.py
  class sfp_openphish (line 16) | class sfp_openphish(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method queryBlacklist (line 80) | def queryBlacklist(self, target):
    method retrieveBlacklist (line 92) | def retrieveBlacklist(self):
    method parseBlacklist (line 118) | def parseBlacklist(self, blacklist):
    method handleEvent (line 151) | def handleEvent(self, event):

FILE: modules/sfp_openstreetmap.py
  class sfp_openstreetmap (line 24) | class sfp_openstreetmap(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method query (line 70) | def query(self, qry):
    method handleEvent (line 93) | def handleEvent(self, event):

FILE: modules/sfp_pageinfo.py
  class sfp_pageinfo (line 31) | class sfp_pageinfo(SpiderFootPlugin):
    method setup (line 47) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 62) | def producedEvents(self):
    method handleEvent (line 67) | def handleEvent(self, event):

FILE: modules/sfp_pastebin.py
  class sfp_pastebin (line 19) | class sfp_pastebin(SpiderFootPlugin):
    method setup (line 69) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 78) | def watchedEvents(self):
    method producedEvents (line 84) | def producedEvents(self):
    method handleEvent (line 87) | def handleEvent(self, event):

FILE: modules/sfp_pgp.py
  class sfp_pgp (line 18) | class sfp_pgp(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method queryDomain (line 67) | def queryDomain(self, keyserver_search_url, qry):
    method queryEmail (line 85) | def queryEmail(self, keyserver_fetch_url, qry):
    method handleEvent (line 103) | def handleEvent(self, event):

FILE: modules/sfp_phishstats.py
  class sfp_phishstats (line 24) | class sfp_phishstats(SpiderFootPlugin):
    method setup (line 62) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method queryIPAddress (line 93) | def queryIPAddress(self, qry):
    method handleEvent (line 121) | def handleEvent(self, event):

FILE: modules/sfp_phishtank.py
  class sfp_phishtank (line 16) | class sfp_phishtank(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 59) | def watchedEvents(self):
    method producedEvents (line 66) | def producedEvents(self):
    method queryBlacklist (line 76) | def queryBlacklist(self, target):
    method retrieveBlacklist (line 91) | def retrieveBlacklist(self):
    method parseBlacklist (line 117) | def parseBlacklist(self, blacklist):
    method handleEvent (line 150) | def handleEvent(self, event):

FILE: modules/sfp_phone.py
  class sfp_phone (line 22) | class sfp_phone(SpiderFootPlugin):
    method setup (line 37) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 44) | def watchedEvents(self):
    method producedEvents (line 47) | def producedEvents(self):
    method handleEvent (line 50) | def handleEvent(self, event):

FILE: modules/sfp_portscan_tcp.py
  class sfp_portscan_tcp (line 23) | class sfp_portscan_tcp(SpiderFootPlugin):
    method setup (line 65) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 97) | def watchedEvents(self):
    method producedEvents (line 101) | def producedEvents(self):
    method tryPort (line 104) | def tryPort(self, ip, port):
    method tryPortWrapper (line 130) | def tryPortWrapper(self, ip, portList):
    method sendEvent (line 158) | def sendEvent(self, resArray, srcEvent):
    method handleEvent (line 173) | def handleEvent(self, event):

FILE: modules/sfp_projectdiscovery.py
  class sfp_projectdiscovery (line 18) | class sfp_projectdiscovery(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method query (line 73) | def query(self, qry):
    method handleEvent (line 96) | def handleEvent(self, event):

FILE: modules/sfp_psbdmp.py
  class sfp_psbdmp (line 18) | class sfp_psbdmp(SpiderFootPlugin):
    method setup (line 46) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 53) | def watchedEvents(self):
    method producedEvents (line 56) | def producedEvents(self):
    method query (line 59) | def query(self, qry):
    method handleEvent (line 91) | def handleEvent(self, event):

FILE: modules/sfp_pulsedive.py
  class sfp_pulsedive (line 25) | class sfp_pulsedive(SpiderFootPlugin):
    method setup (line 85) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 93) | def watchedEvents(self):
    method producedEvents (line 107) | def producedEvents(self):
    method query (line 113) | def query(self, qry):
    method handleEvent (line 145) | def handleEvent(self, event):

FILE: modules/sfp_punkspider.py
  class sfp_punkspider (line 18) | class sfp_punkspider(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 60) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method query (line 67) | def query(self, domain: str):
    method parseApiResponse (line 74) | def parseApiResponse(self, res: dict):
    method handleEvent (line 104) | def handleEvent(self, event):

FILE: modules/sfp_quad9.py
  class sfp_quad9 (line 19) | class sfp_quad9(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 60) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method query (line 77) | def query(self, qry):
    method handleEvent (line 92) | def handleEvent(self, event):

FILE: modules/sfp_reversewhois.py
  class sfp_reversewhois (line 20) | class sfp_reversewhois(SpiderFootPlugin):
    method setup (line 48) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 60) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method query (line 68) | def query(self, qry):
    method handleEvent (line 103) | def handleEvent(self, event):

FILE: modules/sfp_ripe.py
  class sfp_ripe (line 20) | class sfp_ripe(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 70) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method fetchRir (line 95) | def fetchRir(self, url):
    method ipNetblock (line 108) | def ipNetblock(self, ipaddr):
    method queryWhois (line 130) | def queryWhois(self, qry):
    method netblockAs (line 145) | def netblockAs(self, prefix):
    method entityOwnerInfo (line 172) | def entityOwnerInfo(self, entity):
    method asNetblocks (line 208) | def asNetblocks(self, asn):
    method asNeighbours (line 230) | def asNeighbours(self, asn):
    method findName (line 251) | def findName(self, string):
    method ownsAs (line 287) | def ownsAs(self, asn):
    method ownsNetblock (line 303) | def ownsNetblock(self, netblock):
    method handleEvent (line 319) | def handleEvent(self, event):

FILE: modules/sfp_riskiq.py
  class sfp_riskiq (line 19) | class sfp_riskiq(SpiderFootPlugin):
    method setup (line 76) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 88) | def watchedEvents(self):
    method producedEvents (line 92) | def producedEvents(self):
    method query (line 97) | def query(self, qry, qtype, opts=dict()):
    method handleEvent (line 152) | def handleEvent(self, event):

FILE: modules/sfp_robtex.py
  class sfp_robtex (line 21) | class sfp_robtex(SpiderFootPlugin):
    method setup (line 74) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 84) | def watchedEvents(self):
    method producedEvents (line 95) | def producedEvents(self):
    method handleEvent (line 99) | def handleEvent(self, event):

FILE: modules/sfp_s3bucket.py
  class sfp_s3bucket (line 21) | class sfp_s3bucket(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method checkSite (line 74) | def checkSite(self, url):
    method threadSites (line 95) | def threadSites(self, siteList):
    method batchSites (line 125) | def batchSites(self, sites):
    method handleEvent (line 149) | def handleEvent(self, event):

FILE: modules/sfp_searchcode.py
  class sfp_searchcode (line 22) | class sfp_searchcode(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 66) | def producedEvents(self):
    method query (line 75) | def query(self, qry, page=1, per_page=100):
    method handleEvent (line 111) | def handleEvent(self, event):

FILE: modules/sfp_securitytrails.py
  class sfp_securitytrails (line 19) | class sfp_securitytrails(SpiderFootPlugin):
    method setup (line 72) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 84) | def watchedEvents(self):
    method producedEvents (line 89) | def producedEvents(self):
    method query (line 96) | def query(self, qry, querytype, page=1, accum=None):
    method handleEvent (line 149) | def handleEvent(self, event):

FILE: modules/sfp_seon.py
  class sfp_seon (line 19) | class sfp_seon(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 79) | def producedEvents(self):
    method query (line 101) | def query(self, qry, eventName):
    method handleEvent (line 136) | def handleEvent(self, event):

FILE: modules/sfp_shodan.py
  class sfp_shodan (line 24) | class sfp_shodan(SpiderFootPlugin):
    method setup (line 71) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 79) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method queryHost (line 91) | def queryHost(self, qry):
    method searchHosts (line 120) | def searchHosts(self, qry):
    method searchHtml (line 154) | def searchHtml(self, qry):
    method handleEvent (line 192) | def handleEvent(self, event):

FILE: modules/sfp_similar.py
  class sfp_similar (line 61) | class sfp_similar(SpiderFootPlugin):
    method setup (line 84) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 93) | def watchedEvents(self):
    method producedEvents (line 99) | def producedEvents(self):
    method handleEvent (line 103) | def handleEvent(self, event):

FILE: modules/sfp_skymem.py
  class sfp_skymem (line 19) | class sfp_skymem(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 57) | def watchedEvents(self):
    method producedEvents (line 63) | def producedEvents(self):
    method handleEvent (line 67) | def handleEvent(self, event):

FILE: modules/sfp_slideshare.py
  class sfp_slideshare (line 17) | class sfp_slideshare(SpiderFootPlugin):
    method setup (line 50) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 58) | def watchedEvents(self):
    method producedEvents (line 62) | def producedEvents(self):
    method extractMeta (line 66) | def extractMeta(self, meta_property, html):
    method handleEvent (line 70) | def handleEvent(self, event):

FILE: modules/sfp_snov.py
  class sfp_snov (line 22) | class sfp_snov(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method queryAccessToken (line 84) | def queryAccessToken(self):
    method queryDomainName (line 122) | def queryDomainName(self, qry, accessToken, currentLastId):
    method handleEvent (line 148) | def handleEvent(self, event):

FILE: modules/sfp_social.py
  class sfp_social (line 36) | class sfp_social(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method handleEvent (line 67) | def handleEvent(self, event):

FILE: modules/sfp_sociallinks.py
  class sfp_sociallinks (line 19) | class sfp_sociallinks(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 74) | def producedEvents(self):
    method query (line 86) | def query(self, queryString):
    method queryTelegram (line 117) | def queryTelegram(self, qry, eventName):
    method queryFlickr (line 125) | def queryFlickr(self, qry):
    method querySkype (line 130) | def querySkype(self, qry):
    method queryLinkedin (line 135) | def queryLinkedin(self, qry):
    method handleEvent (line 141) | def handleEvent(self, event):

FILE: modules/sfp_socialprofiles.py
  class sfp_socialprofiles (line 47) | class sfp_socialprofiles(SpiderFootPlugin):
    method setup (line 109) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 119) | def watchedEvents(self):
    method producedEvents (line 125) | def producedEvents(self):
    method handleEvent (line 129) | def handleEvent(self, event):

FILE: modules/sfp_sorbs.py
  class sfp_sorbs (line 20) | class sfp_sorbs(SpiderFootPlugin):
    method setup (line 98) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 105) | def watchedEvents(self):
    method producedEvents (line 113) | def producedEvents(self):
    method reverseAddr (line 127) | def reverseAddr(self, ipaddr):
    method queryAddr (line 133) | def queryAddr(self, qaddr):
    method handleEvent (line 155) | def handleEvent(self, event):

FILE: modules/sfp_spamcop.py
  class sfp_spamcop (line 20) | class sfp_spamcop(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method reverseAddr (line 89) | def reverseAddr(self, ipaddr):
    method queryAddr (line 95) | def queryAddr(self, qaddr):
    method handleEvent (line 117) | def handleEvent(self, event):

FILE: modules/sfp_spamhaus.py
  class sfp_spamhaus (line 20) | class sfp_spamhaus(SpiderFootPlugin):
    method setup (line 78) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 86) | def watchedEvents(self):
    method producedEvents (line 94) | def producedEvents(self):
    method reverseAddr (line 107) | def reverseAddr(self, ipaddr):
    method queryAddr (line 113) | def queryAddr(self, qaddr):
    method handleEvent (line 135) | def handleEvent(self, event):

FILE: modules/sfp_spider.py
  class sfp_spider (line 20) | class sfp_spider(SpiderFootPlugin):
    method setup (line 76) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 87) | def watchedEvents(self):
    method producedEvents (line 91) | def producedEvents(self):
    method processUrl (line 101) | def processUrl(self, url: str) -> dict:
    method cleanLinks (line 191) | def cleanLinks(self, links: list) -> list:
    method linkNotify (line 240) | def linkNotify(self, url: str, parentEvent=None):
    method contentNotify (line 253) | def contentNotify(self, url: str, httpresult: dict, parentEvent=None) ...
    method handleEvent (line 306) | def handleEvent(self, event) -> None:
    method spiderFrom (line 361) | def spiderFrom(self, startingPoint: str) -> None:

FILE: modules/sfp_spur.py
  class sfp_spur (line 21) | class sfp_spur(SpiderFootPlugin):
    method setup (line 73) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 82) | def watchedEvents(self):
    method producedEvents (line 91) | def producedEvents(self):
    method queryIPAddress (line 103) | def queryIPAddress(self, ipAddr):
    method handleEvent (line 134) | def handleEvent(self, event):

FILE: modules/sfp_spyonweb.py
  class sfp_spyonweb (line 21) | class sfp_spyonweb(SpiderFootPlugin):
    method setup (line 75) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 84) | def watchedEvents(self):
    method producedEvents (line 88) | def producedEvents(self):
    method query (line 94) | def query(self, endpoint, qry, limit=100):
    method queryGoogleAnalytics (line 144) | def queryGoogleAnalytics(self, qry, limit=100):
    method queryGoogleAdsense (line 156) | def queryGoogleAdsense(self, qry, limit=100):
    method queryIP (line 168) | def queryIP(self, qry, limit=100):
    method querySummary (line 180) | def querySummary(self, qry, limit=100):
    method handleEvent (line 192) | def handleEvent(self, event):

FILE: modules/sfp_sslcert.py
  class sfp_sslcert (line 18) | class sfp_sslcert(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method handleEvent (line 76) | def handleEvent(self, event):

FILE: modules/sfp_stackoverflow.py
  class sfp_stackoverflow (line 20) | class sfp_stackoverflow(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 73) | def watchedEvents(self):
    method producedEvents (line 77) | def producedEvents(self):
    method query (line 88) | def query(self, qry, qryType):
    method extractUsername (line 136) | def extractUsername(self, questionId):
    method extractIP4s (line 151) | def extractIP4s(self, text):
    method extractIP6s (line 165) | def extractIP6s(self, text):
    method handleEvent (line 179) | def handleEvent(self, event):

FILE: modules/sfp_stevenblack_hosts.py
  class sfp_stevenblack_hosts (line 17) | class sfp_stevenblack_hosts(SpiderFootPlugin):
    method setup (line 48) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 56) | def watchedEvents(self):
    method producedEvents (line 63) | def producedEvents(self):
    method queryBlocklist (line 73) | def queryBlocklist(self, target):
    method retrieveBlocklist (line 85) | def retrieveBlocklist(self):
    method parseBlocklist (line 112) | def parseBlocklist(self, blocklist):
    method handleEvent (line 141) | def handleEvent(self, event):

FILE: modules/sfp_strangeheaders.py
  class sfp_strangeheaders (line 82) | class sfp_strangeheaders(SpiderFootPlugin):
    method setup (line 97) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 106) | def watchedEvents(self):
    method producedEvents (line 110) | def producedEvents(self):
    method handleEvent (line 114) | def handleEvent(self, event):

FILE: modules/sfp_subdomain_takeover.py
  class sfp_subdomain_takeover (line 20) | class sfp_subdomain_takeover(SpiderFootPlugin):
    method setup (line 43) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 72) | def watchedEvents(self):
    method producedEvents (line 76) | def producedEvents(self):
    method handleEvent (line 80) | def handleEvent(self, event):

FILE: modules/sfp_sublist3r.py
  class sfp_sublist3r (line 19) | class sfp_sublist3r(SpiderFootPlugin):
    method setup (line 41) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 47) | def watchedEvents(self):
    method producedEvents (line 50) | def producedEvents(self):
    method query (line 53) | def query(self, domain):
    method sendEvent (line 78) | def sendEvent(self, source, host):
    method handleEvent (line 85) | def handleEvent(self, event):

FILE: modules/sfp_surbl.py
  class sfp_surbl (line 19) | class sfp_surbl(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 69) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method reverseAddr (line 99) | def reverseAddr(self, ipaddr):
    method query (line 105) | def query(self, qaddr):
    method handleEvent (line 128) | def handleEvent(self, event):

FILE: modules/sfp_talosintel.py
  class sfp_talosintel (line 19) | class sfp_talosintel(SpiderFootPlugin):
    method setup (line 63) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 72) | def watchedEvents(self):
    method producedEvents (line 81) | def producedEvents(self):
    method queryBlacklist (line 93) | def queryBlacklist(self, target, targetType):
    method retrieveBlacklist (line 112) | def retrieveBlacklist(self):
    method parseBlacklist (line 140) | def parseBlacklist(self, blacklist):
    method handleEvent (line 165) | def handleEvent(self, event):

FILE: modules/sfp_template.py
  class sfp_template (line 20) | class sfp_template(SpiderFootPlugin):
    method setup (line 184) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 207) | def watchedEvents(self):
    method producedEvents (line 216) | def producedEvents(self):
    method query (line 229) | def query(self, qry):
    method handleEvent (line 261) | def handleEvent(self, event):

FILE: modules/sfp_textmagic.py
  class sfp_textmagic (line 18) | class sfp_textmagic(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 65) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method handle_error_response (line 76) | def handle_error_response(self, qry, res):
    method queryPhoneNumber (line 91) | def queryPhoneNumber(self, qry):
    method handleEvent (line 119) | def handleEvent(self, event):

FILE: modules/sfp_threatcrowd.py
  class sfp_threatcrowd (line 20) | class sfp_threatcrowd(SpiderFootPlugin):
    method setup (line 68) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 80) | def watchedEvents(self):
    method producedEvents (line 86) | def producedEvents(self):
    method query (line 92) | def query(self, qry):
    method handleEvent (line 119) | def handleEvent(self, event):

FILE: modules/sfp_threatfox.py
  class sfp_threatfox (line 19) | class sfp_threatfox(SpiderFootPlugin):
    method setup (line 52) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 59) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method query (line 73) | def query(self, qry):
    method handleEvent (line 138) | def handleEvent(self, event):

FILE: modules/sfp_threatjammer.py
  class sfp_threatjammer (line 19) | class sfp_threatjammer(SpiderFootPlugin):
    method setup (line 69) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 77) | def watchedEvents(self):
    method producedEvents (line 85) | def producedEvents(self):
    method queryIp (line 93) | def queryIp(self, ip):
    method handleEvent (line 152) | def handleEvent(self, event):

FILE: modules/sfp_threatminer.py
  class sfp_threatminer (line 22) | class sfp_threatminer(SpiderFootPlugin):
    method setup (line 76) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 90) | def watchedEvents(self):
    method producedEvents (line 95) | def producedEvents(self):
    method query (line 98) | def query(self, qry, querytype):
    method handleEvent (line 129) | def handleEvent(self, event):

FILE: modules/sfp_tldsearch.py
  class sfp_tldsearch (line 23) | class sfp_tldsearch(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method tryTld (line 73) | def tryTld(self, target, tld):
    method tryTldWrapper (line 95) | def tryTldWrapper(self, tldList, sourceEvent):
    method sendEvent (line 127) | def sendEvent(self, source, result):
    method handleEvent (line 149) | def handleEvent(self, event):

FILE: modules/sfp_tool_cmseek.py
  class sfp_tool_cmseek (line 22) | class sfp_tool_cmseek(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_tool_dnstwist.py
  class sfp_tool_dnstwist (line 22) | class sfp_tool_dnstwist(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 74) | def producedEvents(self):
    method handleEvent (line 78) | def handleEvent(self, event):

FILE: modules/sfp_tool_nbtscan.py
  class sfp_tool_nbtscan (line 22) | class sfp_tool_nbtscan(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method handleEvent (line 72) | def handleEvent(self, event):

FILE: modules/sfp_tool_nmap.py
  class sfp_tool_nmap (line 21) | class sfp_tool_nmap(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 74) | def producedEvents(self):
    method handleEvent (line 78) | def handleEvent(self, event):

FILE: modules/sfp_tool_nuclei.py
  class sfp_tool_nuclei (line 24) | class sfp_tool_nuclei(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 71) | def watchedEvents(self):
    method producedEvents (line 74) | def producedEvents(self):
    method handleEvent (line 86) | def handleEvent(self, event):

FILE: modules/sfp_tool_onesixtyone.py
  class sfp_tool_onesixtyone (line 23) | class sfp_tool_onesixtyone(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 79) | def producedEvents(self):
    method handleEvent (line 86) | def handleEvent(self, event):

FILE: modules/sfp_tool_retirejs.py
  class sfp_tool_retirejs (line 23) | class sfp_tool_retirejs(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 60) | def watchedEvents(self):
    method producedEvents (line 63) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_tool_snallygaster.py
  class sfp_tool_snallygaster (line 22) | class sfp_tool_snallygaster(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 66) | def producedEvents(self):
    method handleEvent (line 75) | def handleEvent(self, event):

FILE: modules/sfp_tool_testsslsh.py
  class sfp_tool_testsslsh (line 24) | class sfp_tool_testsslsh(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 69) | def watchedEvents(self):
    method producedEvents (line 72) | def producedEvents(self):
    method handleEvent (line 82) | def handleEvent(self, event):

FILE: modules/sfp_tool_trufflehog.py
  class sfp_tool_trufflehog (line 22) | class sfp_tool_trufflehog(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 67) | def producedEvents(self):
    method handleEvent (line 70) | def handleEvent(self, event):

FILE: modules/sfp_tool_wafw00f.py
  class sfp_tool_wafw00f (line 21) | class sfp_tool_wafw00f(SpiderFootPlugin):
    method setup (line 49) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 58) | def watchedEvents(self):
    method producedEvents (line 61) | def producedEvents(self):
    method handleEvent (line 64) | def handleEvent(self, event):

FILE: modules/sfp_tool_wappalyzer.py
  class sfp_tool_wappalyzer (line 22) | class sfp_tool_wappalyzer(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 64) | def producedEvents(self):
    method handleEvent (line 68) | def handleEvent(self, event):

FILE: modules/sfp_tool_whatweb.py
  class sfp_tool_whatweb (line 21) | class sfp_tool_whatweb(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_torch.py
  class sfp_torch (line 20) | class sfp_torch(SpiderFootPlugin):
    method setup (line 54) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 61) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method handleEvent (line 74) | def handleEvent(self, event):

FILE: modules/sfp_torexits.py
  class sfp_torexits (line 21) | class sfp_torexits(SpiderFootPlugin):
    method setup (line 56) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 65) | def watchedEvents(self):
    method producedEvents (line 75) | def producedEvents(self):
    method queryExitNodes (line 82) | def queryExitNodes(self, ip):
    method retrieveExitNodes (line 95) | def retrieveExitNodes(self):
    method parseExitNodes (line 121) | def parseExitNodes(self, data):
    method handleEvent (line 172) | def handleEvent(self, event):

FILE: modules/sfp_trashpanda.py
  class sfp_trashpanda (line 21) | class sfp_trashpanda(SpiderFootPlugin):
    method setup (line 59) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 77) | def producedEvents(self):
    method query (line 84) | def query(self, qry, eventName):
    method handleEvent (line 113) | def handleEvent(self, event):

FILE: modules/sfp_trumail.py
  class sfp_trumail (line 19) | class sfp_trumail(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 60) | def watchedEvents(self):
    method producedEvents (line 65) | def producedEvents(self):
    method queryEmailAddr (line 71) | def queryEmailAddr(self, qry):
    method handleEvent (line 90) | def handleEvent(self, event):

FILE: modules/sfp_twilio.py
  class sfp_twilio (line 19) | class sfp_twilio(SpiderFootPlugin):
    method setup (line 61) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 68) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method queryPhoneNumber (line 76) | def queryPhoneNumber(self, phoneNumber):
    method handleEvent (line 115) | def handleEvent(self, event):

FILE: modules/sfp_twitter.py
  class sfp_twitter (line 17) | class sfp_twitter(SpiderFootPlugin):
    method setup (line 45) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 54) | def watchedEvents(self):
    method producedEvents (line 58) | def producedEvents(self):
    method handleEvent (line 62) | def handleEvent(self, event):

FILE: modules/sfp_uceprotect.py
  class sfp_uceprotect (line 20) | class sfp_uceprotect(SpiderFootPlugin):
    method setup (line 60) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 67) | def watchedEvents(self):
    method producedEvents (line 75) | def producedEvents(self):
    method reverseAddr (line 88) | def reverseAddr(self, ipaddr):
    method queryDnsblLevel1 (line 91) | def queryDnsblLevel1(self, qaddr):
    method queryDnsblLevel2 (line 113) | def queryDnsblLevel2(self, qaddr):
    method handleEvent (line 135) | def handleEvent(self, event):

FILE: modules/sfp_urlscan.py
  class sfp_urlscan (line 21) | class sfp_urlscan(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 70) | def producedEvents(self):
    method query (line 76) | def query(self, qry):
    method handleEvent (line 102) | def handleEvent(self, event):

FILE: modules/sfp_venmo.py
  class sfp_venmo (line 18) | class sfp_venmo(SpiderFootPlugin):
    method setup (line 46) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 54) | def watchedEvents(self):
    method producedEvents (line 58) | def producedEvents(self):
    method query (line 62) | def query(self, qry):
    method handleEvent (line 88) | def handleEvent(self, event):

FILE: modules/sfp_viewdns.py
  class sfp_viewdns (line 21) | class sfp_viewdns(SpiderFootPlugin):
    method setup (line 67) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 83) | def producedEvents(self):
    method query (line 90) | def query(self, qry, querytype, page=1):
    method handleEvent (line 161) | def handleEvent(self, event):

FILE: modules/sfp_virustotal.py
  class sfp_virustotal (line 24) | class sfp_virustotal(SpiderFootPlugin):
    method setup (line 79) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 86) | def watchedEvents(self):
    method producedEvents (line 96) | def producedEvents(self):
    method queryIp (line 111) | def queryIp(self, qry):
    method queryDomain (line 139) | def queryDomain(self, qry):
    method handleEvent (line 172) | def handleEvent(self, event):

FILE: modules/sfp_voipbl.py
  class sfp_voipbl (line 19) | class sfp_voipbl(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 74) | def producedEvents(self):
    method queryBlacklist (line 86) | def queryBlacklist(self, target, targetType):
    method retrieveBlacklist (line 105) | def retrieveBlacklist(self):
    method parseBlacklist (line 131) | def parseBlacklist(self, blacklist):
    method handleEvent (line 160) | def handleEvent(self, event):

FILE: modules/sfp_vxvault.py
  class sfp_vxvault (line 16) | class sfp_vxvault(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 78) | def producedEvents(self):
    method queryBlacklist (line 87) | def queryBlacklist(self, target):
    method retrieveBlacklist (line 99) | def retrieveBlacklist(self):
    method parseBlacklist (line 125) | def parseBlacklist(self, blacklist):
    method handleEvent (line 159) | def handleEvent(self, event):

FILE: modules/sfp_webanalytics.py
  class sfp_webanalytics (line 19) | class sfp_webanalytics(SpiderFootPlugin):
    method setup (line 34) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 42) | def watchedEvents(self):
    method producedEvents (line 46) | def producedEvents(self):
    method handleEvent (line 50) | def handleEvent(self, event):

FILE: modules/sfp_webframework.py
  class sfp_webframework (line 30) | class sfp_webframework(SpiderFootPlugin):
    method setup (line 53) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_webserver.py
  class sfp_webserver (line 19) | class sfp_webserver(SpiderFootPlugin):
    method setup (line 35) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 44) | def watchedEvents(self):
    method producedEvents (line 48) | def producedEvents(self):
    method handleEvent (line 53) | def handleEvent(self, event):

FILE: modules/sfp_whatcms.py
  class sfp_whatcms (line 22) | class sfp_whatcms(SpiderFootPlugin):
    method setup (line 72) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 81) | def watchedEvents(self):
    method producedEvents (line 85) | def producedEvents(self):
    method queryCmsDetect (line 90) | def queryCmsDetect(self, qry):
    method queryCmsTechnology (line 106) | def queryCmsTechnology(self, qry):
    method parseApiResponse (line 121) | def parseApiResponse(self, res: dict):
    method handleEvent (line 196) | def handleEvent(self, event):

FILE: modules/sfp_whois.py
  class sfp_whois (line 21) | class sfp_whois(SpiderFootPlugin):
    method setup (line 41) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 49) | def watchedEvents(self):
    method producedEvents (line 56) | def producedEvents(self):
    method handleEvent (line 62) | def handleEvent(self, event):

FILE: modules/sfp_whoisology.py
  class sfp_whoisology (line 18) | class sfp_whoisology(SpiderFootPlugin):
    method setup (line 64) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 75) | def watchedEvents(self):
    method producedEvents (line 79) | def producedEvents(self):
    method query (line 83) | def query(self, qry, querytype):
    method handleEvent (line 115) | def handleEvent(self, event):

FILE: modules/sfp_whoxy.py
  class sfp_whoxy (line 18) | class sfp_whoxy(SpiderFootPlugin):
    method setup (line 65) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 80) | def producedEvents(self):
    method query (line 84) | def query(self, qry, querytype, page=1, accum=None):
    method handleEvent (line 128) | def handleEvent(self, event):

FILE: modules/sfp_wigle.py
  class sfp_wigle (line 22) | class sfp_wigle(SpiderFootPlugin):
    method setup (line 73) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 85) | def watchedEvents(self):
    method producedEvents (line 89) | def producedEvents(self):
    method getnetworks (line 92) | def getnetworks(self, coords):
    method validApiKey (line 144) | def validApiKey(self, api_key):
    method handleEvent (line 157) | def handleEvent(self, event):

FILE: modules/sfp_wikileaks.py
  class sfp_wikileaks (line 18) | class sfp_wikileaks(SpiderFootPlugin):
    method setup (line 55) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 63) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method handleEvent (line 73) | def handleEvent(self, event):

FILE: modules/sfp_wikipediaedits.py
  class sfp_wikipediaedits (line 24) | class sfp_wikipediaedits(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 65) | def watchedEvents(self):
    method producedEvents (line 68) | def producedEvents(self):
    method query (line 71) | def query(self, qry):
    method handleEvent (line 112) | def handleEvent(self, event):

FILE: modules/sfp_xforce.py
  class sfp_xforce (line 24) | class sfp_xforce(SpiderFootPlugin):
    method setup (line 93) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 101) | def watchedEvents(self):
    method producedEvents (line 113) | def producedEvents(self):
    method query (line 130) | def query(self, qry, querytype):
    method parseApiResponse (line 154) | def parseApiResponse(self, res: dict):
    method handleEvent (line 203) | def handleEvent(self, event):

FILE: modules/sfp_yandexdns.py
  class sfp_yandexdns (line 19) | class sfp_yandexdns(SpiderFootPlugin):
    method setup (line 57) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 64) | def watchedEvents(self):
    method producedEvents (line 71) | def producedEvents(self):
    method queryAddr (line 82) | def queryAddr(self, qaddr):
    method handleEvent (line 96) | def handleEvent(self, event):

FILE: modules/sfp_zetalytics.py
  class sfp_zetalytics (line 19) | class sfp_zetalytics(SpiderFootPlugin):
    method setup (line 51) | def setup(self, sfc, userOpts=None):
    method watchedEvents (line 57) | def watchedEvents(self):
    method producedEvents (line 60) | def producedEvents(self):
    method emit (line 63) | def emit(self, etype, data, pevent):
    method verify_emit_internet_name (line 70) | def verify_emit_internet_name(self, hostname, pevent):
    method request (line 88) | def request(self, path, params):
    method query_subdomains (line 107) | def query_subdomains(self, domain):
    method query_hostname (line 110) | def query_hostname(self, hostname):
    method query_email_domain (line 113) | def query_email_domain(self, email_domain):
    method query_email_address (line 116) | def query_email_address(self, email_address):
    method generate_subdomains_events (line 119) | def generate_subdomains_events(self, data, pevent):
    method generate_hostname_events (line 137) | def generate_hostname_events(self, data, pevent):
    method generate_email_events (line 158) | def generate_email_events(self, data, pevent):
    method generate_email_domain_events (line 175) | def generate_email_domain_events(self, data, pevent):
    method handleEvent (line 192) | def handleEvent(self, event):

FILE: modules/sfp_zonefiles.py
  class sfp_zonefiles (line 19) | class sfp_zonefiles(SpiderFootPlugin):
    method setup (line 58) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 66) | def watchedEvents(self):
    method producedEvents (line 69) | def producedEvents(self):
    method queryDomain (line 79) | def queryDomain(self, qry):
    method parseApiResponse (line 103) | def parseApiResponse(self, res: dict):
    method handleEvent (line 141) | def handleEvent(self, event):

FILE: modules/sfp_zoneh.py
  class sfp_zoneh (line 19) | class sfp_zoneh(SpiderFootPlugin):
    method setup (line 63) | def setup(self, sfc, userOpts=dict()):
    method watchedEvents (line 76) | def watchedEvents(self):
    method producedEvents (line 84) | def producedEvents(self):
    method lookupItem (line 89) | def lookupItem(self, target, content):
    method handleEvent (line 99) | def handleEvent(self, event):

FILE: sf.py
  function main (line 42) | def main() -> None:
  function start_scan (line 235) | def start_scan(sfConfig: dict, sfModules: dict, args, loggingQueue) -> N...
  function start_web_server (line 461) | def start_web_server(sfWebUiConfig: dict, sfConfig: dict, loggingQueue=N...
  function handle_abort (line 589) | def handle_abort(signal, frame) -> None:

FILE: sfcli.py
  class bcolors (line 46) | class bcolors:
  class SpiderFootCli (line 56) | class SpiderFootCli(cmd.Cmd):
    method default (line 81) | def default(self, line):
    method complete_start (line 88) | def complete_start(self, text, line, startidx, endidx):
    method complete_find (line 91) | def complete_find(self, text, line, startidx, endidx):
    method complete_data (line 94) | def complete_data(self, text, line, startidx, endidx):
    method complete_default (line 98) | def complete_default(self, text, line, startidx, endidx):
    method dprint (line 118) | def dprint(self, msg, err=False, deb=False, plain=False, color=None):
    method do_debug (line 160) | def do_debug(self, line):
    method do_spool (line 169) | def do_spool(self, line):
    method do_history (line 184) | def do_history(self, line):
    method precmd (line 205) | def precmd(self, line):
    method ddprint (line 220) | def ddprint(self, msg):
    method edprint (line 224) | def edprint(self, msg):
    method pretty (line 228) | def pretty(self, data, titlemap=None):
    method request (line 348) | def request(self, url, post=None):
    method emptyline (line 399) | def emptyline(self):
    method completedefault (line 402) | def completedefault(self, text, line, begidx, endidx):
    method myparseline (line 408) | def myparseline(self, cmdline, replace=True):
    method send_output (line 449) | def send_output(self, data, cmd, titles=None, total=True, raw=False):
    method do_query (line 536) | def do_query(self, line):
    method do_ping (line 555) | def do_ping(self, line):
    method do_modules (line 574) | def do_modules(self, line, cacheonly=False):
    method do_correlationrules (line 591) | def do_correlationrules(self, line, cacheonly=False):
    method do_types (line 609) | def do_types(self, line, cacheonly=False):
    method do_load (line 633) | def do_load(self, line):
    method do_scaninfo (line 639) | def do_scaninfo(self, line):
    method do_scans (line 673) | def do_scans(self, line):
    method do_correlations (line 707) | def do_correlations(self, line):
    method do_data (line 746) | def do_data(self, line):
    method do_export (line 792) | def do_export(self, line):
    method do_logs (line 854) | def do_logs(self, line):
    method do_start (line 954) | def do_start(self, line):
    method do_stop (line 1022) | def do_stop(self, line):
    method do_search (line 1036) | def do_search(self, line):
    method do_find (line 1042) | def do_find(self, line):
    method do_summary (line 1086) | def do_summary(self, line):
    method do_delete (line 1123) | def do_delete(self, line):
    method print_topics (line 1137) | def print_topics(self, header, cmds, cmdlen, maxcol):
    method do_set (line 1176) | def do_set(self, line):
    method do_shell (line 1325) | def do_shell(self, line):
    method do_clear (line 1331) | def do_clear(self, line):
    method do_exit (line 1337) | def do_exit(self, line):
    method do_EOF (line 1343) | def do_EOF(self, line):

FILE: sflib.py
  class SpiderFoot (line 44) | class SpiderFoot:
    method __init__ (line 58) | def __init__(self, options: dict) -> None:
    method dbh (line 83) | def dbh(self):
    method scanId (line 92) | def scanId(self) -> str:
    method socksProxy (line 101) | def socksProxy(self) -> str:
    method dbh (line 110) | def dbh(self, dbh):
    method scanId (line 121) | def scanId(self, scanId: str) -> str:
    method socksProxy (line 130) | def socksProxy(self, socksProxy: str) -> str:
    method optValueToData (line 142) | def optValueToData(self, val: str) -> str:
    method error (line 182) | def error(self, message: str) -> None:
    method fatal (line 193) | def fatal(self, error: str) -> None:
    method status (line 205) | def status(self, message: str) -> None:
    method info (line 216) | def info(self, message: str) -> None:
    method debug (line 227) | def debug(self, message: str) -> None:
    method hashstring (line 240) | def hashstring(self, string: str) -> str:
    method cachePut (line 254) | def cachePut(self, label: str, data: str) -> None:
    method cacheGet (line 276) | def cacheGet(self, label: str, timeoutHrs: int) -> str:
    method configSerialize (line 306) | def configSerialize(self, opts: dict, filterSystem: bool = True):
    method configUnserialize (line 370) | def configUnserialize(self, opts: dict, referencePoint: dict, filterSy...
    method modulesProducing (line 465) | def modulesProducing(self, events: list) -> list:
    method modulesConsuming (line 499) | def modulesConsuming(self, events: list) -> list:
    method eventsFromModules (line 534) | def eventsFromModules(self, modules: list) -> list:
    method eventsToModules (line 562) | def eventsToModules(self, modules: list) -> list:
    method urlFQDN (line 590) | def urlFQDN(self, url: str) -> str:
    method domainKeyword (line 612) | def domainKeyword(self, domain: str, tldList: list) -> str:
    method domainKeywords (line 640) | def domainKeywords(self, domainList: list, tldList: list) -> set:
    method hostDomain (line 661) | def hostDomain(self, hostname: str, tldList: list) -> str:
    method validHost (line 679) | def validHost(self, hostname: str, tldList: str) -> bool:
    method isDomain (line 704) | def isDomain(self, hostname: str, tldList: list) -> bool:
    method validIP (line 728) | def validIP(self, address: str) -> bool:
    method validIP6 (line 741) | def validIP6(self, address: str) -> bool:
    method validIpNetwork (line 754) | def validIpNetwork(self, cidr: str) -> bool:
    method isPublicIpAddress (line 774) | def isPublicIpAddress(self, ip: str) -> bool:
    method normalizeDNS (line 801) | def normalizeDNS(self, res: list) -> list:
    method resolveHost (line 827) | def resolveHost(self, host: str) -> list:
    method resolveIP (line 855) | def resolveIP(self, ipaddr: str) -> list:
    method resolveHost6 (line 885) | def resolveHost6(self, hostname: str) -> list:
    method validateIP (line 916) | def validateIP(self, host: str, ip: str) -> bool:
    method safeSocket (line 943) | def safeSocket(self, host: str, port: int, timeout: int) -> 'ssl.SSLSo...
    method safeSSLSocket (line 958) | def safeSSLSocket(self, host: str, port: int, timeout: int) -> 'ssl.SS...
    method parseCert (line 976) | def parseCert(self, rawcert: str, fqdn: str = None, expiringdays: int ...
    method getSession (line 1083) | def getSession(self) -> 'requests.sessions.Session':
    method removeUrlCreds (line 1097) | def removeUrlCreds(self, url: str) -> str:
    method isValidLocalOrLoopbackIp (line 1121) | def isValidLocalOrLoopbackIp(self, ip: str) -> bool:
    method useProxyForUrl (line 1141) | def useProxyForUrl(self, url: str) -> bool:
    method fetchUrl (line 1191) | def fetchUrl(
    method checkDnsWildcard (line 1439) | def checkDnsWildcard(self, target: str) -> bool:
    method cveInfo (line 1459) | def cveInfo(self, cveId: str, sources: str = "circl,nist") -> (str, str):
    method googleIterate (line 1542) | def googleIterate(self, searchString: str, opts: dict = None) -> dict:
    method bingIterate (line 1606) | def bingIterate(self, searchString: str, opts: dict = None) -> dict:

FILE: sfscan.py
  function startSpiderFootScanner (line 26) | def startSpiderFootScanner(loggingQueue, *args, **kwargs):
  class SpiderFootScanner (line 31) | class SpiderFootScanner():
    method __init__ (line 52) | def __init__(self, scanName: str, scanId: str, targetValue: str, targe...
    method scanId (line 222) | def scanId(self) -> str:
    method status (line 226) | def status(self) -> str:
    method __setStatus (line 229) | def __setStatus(self, status: str, started: float = None, ended: float...
    method __startScan (line 260) | def __startScan(self) -> None:
    method runCorrelations (line 428) | def runCorrelations(self) -> None:
    method waitForThreads (line 438) | def waitForThreads(self) -> None:
    method threadsFinished (line 517) | def threadsFinished(self, log_status: bool = False) -> bool:

FILE: sfwebui.py
  class SpiderFootWebUi (line 46) | class SpiderFootWebUi:
    method __init__ (line 55) | def __init__(self: 'SpiderFootWebUi', web_config: dict, config: dict, ...
    method error_page (line 124) | def error_page(self: 'SpiderFootWebUi') -> None:
    method error_page_401 (line 133) | def error_page_401(self: 'SpiderFootWebUi', status: str, message: str,...
    method error_page_404 (line 147) | def error_page_404(self: 'SpiderFootWebUi', status: str, message: str,...
    method jsonify_error (line 162) | def jsonify_error(self: 'SpiderFootWebUi', status: str, message: str) ...
    method error (line 181) | def error(self: 'SpiderFootWebUi', message: str) -> None:
    method cleanUserInput (line 193) | def cleanUserInput(self: 'SpiderFootWebUi', inputList: list) -> list:
    method searchBase (line 226) | def searchBase(self: 'SpiderFootWebUi', id: str = None, eventType: str...
    method buildExcel (line 278) | def buildExcel(self: 'SpiderFootWebUi', data: list, columnNames: list,...
    method scanexportlogs (line 332) | def scanexportlogs(self: 'SpiderFootWebUi', id: str, dialect: str = "e...
    method scancorrelationsexport (line 370) | def scancorrelationsexport(self: 'SpiderFootWebUi', id: str, filetype:...
    method scaneventresultexport (line 440) | def scaneventresultexport(self: 'SpiderFootWebUi', id: str, type: str,...
    method scaneventresultexportmulti (line 491) | def scaneventresultexportmulti(self: 'SpiderFootWebUi', ids: str, file...
    method scansearchresultexport (line 563) | def scansearchresultexport(self: 'SpiderFootWebUi', id: str, eventType...
    method scanexportjsonmulti (line 611) | def scanexportjsonmulti(self: 'SpiderFootWebUi', ids: str) -> str:
    method scanviz (line 665) | def scanviz(self: 'SpiderFootWebUi', id: str, gexf: str = "0") -> str:
    method scanvizmulti (line 703) | def scanvizmulti(self: 'SpiderFootWebUi', ids: str, gexf: str = "1") -...
    method scanopts (line 748) | def scanopts(self: 'SpiderFootWebUi', id: str) -> dict:
    method rerunscan (line 795) | def rerunscan(self: 'SpiderFootWebUi', id: str) -> None:
    method rerunscanmulti (line 855) | def rerunscanmulti(self: 'SpiderFootWebUi', ids: str) -> str:
    method newscan (line 910) | def newscan(self: 'SpiderFootWebUi') -> str:
    method clonescan (line 924) | def clonescan(self: 'SpiderFootWebUi', id: str) -> str:
    method index (line 962) | def index(self: 'SpiderFootWebUi') -> str:
    method scaninfo (line 972) | def scaninfo(self: 'SpiderFootWebUi', id: str) -> str:
    method opts (line 991) | def opts(self: 'SpiderFootWebUi', updated: str = None) -> str:
    method optsexport (line 1006) | def optsexport(self: 'SpiderFootWebUi', pattern: str = None) -> str:
    method optsraw (line 1035) | def optsraw(self: 'SpiderFootWebUi') -> str:
    method scandelete (line 1059) | def scandelete(self: 'SpiderFootWebUi', id: str) -> str:
    method savesettings (line 1088) | def savesettings(self: 'SpiderFootWebUi', allopts: str, token: str, co...
    method savesettingsraw (line 1155) | def savesettingsraw(self: 'SpiderFootWebUi', allopts: str, token: str)...
    method reset_settings (line 1196) | def reset_settings(self: 'SpiderFootWebUi') -> bool:
    method resultsetfp (line 1212) | def resultsetfp(self: 'SpiderFootWebUi', id: str, resultids: str, fp: ...
    method eventtypes (line 1269) | def eventtypes(self: 'SpiderFootWebUi') -> list:
    method modules (line 1288) | def modules(self: 'SpiderFootWebUi') -> list:
    method correlationrules (line 1313) | def correlationrules(self: 'SpiderFootWebUi') -> list:
    method ping (line 1339) | def ping(self: 'SpiderFootWebUi') -> list:
    method query (line 1349) | def query(self: 'SpiderFootWebUi', query: str) -> str:
    method startscan (line 1375) | def startscan(self: 'SpiderFootWebUi', scanname: str, scantarget: str,...
    method stopscan (line 1509) | def stopscan(self: 'SpiderFootWebUi', id: str) -> str:
    method vacuum (line 1547) | def vacuum(self):
    method scanlog (line 1562) | def scanlog(self: 'SpiderFootWebUi', id: str, limit: str = None, rowId...
    method scanerrors (line 1590) | def scanerrors(self: 'SpiderFootWebUi', id: str, limit: str = None) ->...
    method scanlist (line 1616) | def scanlist(self: 'SpiderFootWebUi') -> list:
    method scanstatus (line 1655) | def scanstatus(self: 'SpiderFootWebUi', id: str) -> list:
    method scansummary (line 1688) | def scansummary(self: 'SpiderFootWebUi', id: str, by: str) -> list:
    method scancorrelations (line 1722) | def scancorrelations(self: 'SpiderFootWebUi', id: str) -> list:
    method scaneventresults (line 1747) | def scaneventresults(self: 'SpiderFootWebUi', id: str, eventType: str ...
    method scaneventresultsunique (line 1791) | def scaneventresultsunique(self: 'SpiderFootWebUi', id: str, eventType...
    method search (line 1818) | def search(self: 'SpiderFootWebUi', id: str = None, eventType: str = N...
    method scanhistory (line 1836) | def scanhistory(self: 'SpiderFootWebUi', id: str) -> list:
    method scanelementtypediscovery (line 1857) | def scanelementtypediscovery(self: 'SpiderFootWebUi', id: str, eventTy...

FILE: spiderfoot/correlation.py
  class SpiderFootCorrelator (line 9) | class SpiderFootCorrelator:
    method __init__ (line 49) | def __init__(self, dbh: SpiderFootDb, ruleset: dict, scanId: str = Non...
    method get_ruleset (line 100) | def get_ruleset(self) -> list:
    method run_correlations (line 108) | def run_correlations(self) -> None:
    method build_db_criteria (line 133) | def build_db_criteria(self, matchrule: dict) -> dict:
    method enrich_event_sources (line 218) | def enrich_event_sources(self, events: dict) -> None:
    method enrich_event_children (line 245) | def enrich_event_children(self, events: dict) -> None:
    method enrich_event_entities (line 271) | def enrich_event_entities(self, events: dict) -> None:
    method collect_from_db (line 340) | def collect_from_db(self, matchrule: dict, fetchChildren: bool, fetchS...
    method event_extract (line 390) | def event_extract(self, event: dict, field: str) -> list:
    method event_keep (line 410) | def event_keep(self, event: dict, field: str, patterns: str, patternty...
    method refine_collection (line 463) | def refine_collection(self, matchrule: dict, events: list) -> None:
    method collect_events (line 488) | def collect_events(self, collection: dict, fetchChildren: bool, fetchS...
    method aggregate_events (line 534) | def aggregate_events(self, rule: dict, events: list) -> dict:
    method analyze_events (line 579) | def analyze_events(self, rule: dict, buckets: dict) -> None:
    method analysis_match_all_to_first_collection (line 608) | def analysis_match_all_to_first_collection(self, rule: dict, buckets: ...
    method analysis_first_collection_only (line 676) | def analysis_first_collection_only(self, rule: dict, buckets: dict) ->...
    method analysis_outlier (line 707) | def analysis_outlier(self, rule: dict, buckets: dict) -> None:
    method analysis_threshold (line 744) | def analysis_threshold(self, rule: dict, buckets: dict) -> None:
    method analyze_field_scope (line 777) | def analyze_field_scope(self, field: str) -> list:
    method analyze_rule_scope (line 793) | def analyze_rule_scope(self, rule: dict) -> list:
    method process_rule (line 842) | def process_rule(self, rule: dict) -> list:
    method build_correlation_title (line 897) | def build_correlation_title(self, rule: dict, data: list) -> str:
    method create_correlation (line 929) | def create_correlation(self, rule: dict, data: list, readonly: bool = ...
    method check_ruleset_validity (line 964) | def check_ruleset_validity(self, rules: list) -> bool:
    method check_rule_validity (line 985) | def check_rule_validity(self, rule: dict) -> bool:

FILE: spiderfoot/db.py
  class SpiderFootDb (line 22) | class SpiderFootDb:
    method __init__ (line 286) | def __init__(self, opts: dict, init: bool = False) -> None:
    method create (line 398) | def create(self) -> None:
    method close (line 424) | def close(self) -> None:
    method vacuumDB (line 430) | def vacuumDB(self) -> None:
    method search (line 448) | def search(self, criteria: dict, filterFp: bool = False) -> list:
    method eventTypes (line 531) | def eventTypes(self) -> list:
    method scanLogEvents (line 549) | def scanLogEvents(self, batch: list) -> bool:
    method scanLogEvent (line 595) | def scanLogEvent(self, instanceId: str, classification: str, message: ...
    method scanInstanceCreate (line 641) | def scanInstanceCreate(self, instanceId: str, scanName: str, scanTarge...
    method scanInstanceSet (line 676) | def scanInstanceSet(self, instanceId: str, started: str = None, ended:...
    method scanInstanceGet (line 719) | def scanInstanceGet(self, instanceId: str) -> list:
    method scanResultSummary (line 748) | def scanResultSummary(self, instanceId: str, by: str = "type") -> list:
    method scanCorrelationSummary (line 802) | def scanCorrelationSummary(self, instanceId: str, by: str = "rule") ->...
    method scanCorrelationList (line 847) | def scanCorrelationList(self, instanceId: str) -> list:
    method scanResultEvent (line 879) | def scanResultEvent(
    method scanResultEventUnique (line 977) | def scanResultEventUnique(self, instanceId: str, eventType: str = 'ALL...
    method scanLogs (line 1019) | def scanLogs(self, instanceId: str, limit: int = None, fromRowId: int ...
    method scanErrors (line 1065) | def scanErrors(self, instanceId: str, limit: int = 0) -> list:
    method scanInstanceDelete (line 1102) | def scanInstanceDelete(self, instanceId: str) -> bool:
    method scanResultsUpdateFP (line 1137) | def scanResultsUpdateFP(self, instanceId: str, resultHashes: list, fpF...
    method configSet (line 1176) | def configSet(self, optMap: dict = {}) -> bool:
    method configGet (line 1220) | def configGet(self) -> dict:
    method configClear (line 1247) | def configClear(self) -> None:
    method scanConfigSet (line 1264) | def scanConfigSet(self, scan_id, optMap=dict()) -> None:
    method scanConfigGet (line 1305) | def scanConfigGet(self, instanceId: str) -> dict:
    method scanEventStore (line 1340) | def scanEventStore(self, instanceId: str, sfEvent, truncateSize: int =...
    method scanInstanceList (line 1438) | def scanInstanceList(self) -> list:
    method scanResultHistory (line 1469) | def scanResultHistory(self, instanceId: str) -> list:
    method scanElementSourcesDirect (line 1498) | def scanElementSourcesDirect(self, instanceId: str, elementIdList: lis...
    method scanElementChildrenDirect (line 1549) | def scanElementChildrenDirect(self, instanceId: str, elementIdList: li...
    method scanElementSourcesAll (line 1598) | def scanElementSourcesAll(self, instanceId: str, childData: list) -> l...
    method scanElementChildrenAll (line 1669) | def scanElementChildrenAll(self, instanceId: str, parentIds: list) -> ...
    method correlationResultCreate (line 1717) | def correlationResultCreate(

FILE: spiderfoot/event.py
  class SpiderFootEvent (line 6) | class SpiderFootEvent():
    method __init__ (line 38) | def __init__(self, eventType: str, data: str, module: str, sourceEvent...
    method generated (line 58) | def generated(self) -> float:
    method eventType (line 67) | def eventType(self) -> str:
    method confidence (line 76) | def confidence(self) -> int:
    method visibility (line 85) | def visibility(self) -> int:
    method risk (line 94) | def risk(self) -> int:
    method module (line 103) | def module(self) -> str:
    method data (line 107) | def data(self) -> str:
    method sourceEvent (line 111) | def sourceEvent(self) -> 'SpiderFootEvent':
    method sourceEventHash (line 115) | def sourceEventHash(self) -> str:
    method actualSource (line 119) | def actualSource(self) -> str:
    method moduleDataSource (line 123) | def moduleDataSource(self) -> str:
    method hash (line 127) | def hash(self) -> str:
    method eventType (line 140) | def eventType(self, eventType: str) -> None:
    method confidence (line 159) | def confidence(self, confidence: int) -> None:
    method visibility (line 178) | def visibility(self, visibility: int) -> None:
    method risk (line 197) | def risk(self, risk: int) -> None:
    method module (line 216) | def module(self, module: str) -> None:
    method data (line 235) | def data(self, data: str) -> None:
    method sourceEvent (line 254) | def sourceEvent(self, sourceEvent: 'SpiderFootEvent') -> None:
    method actualSource (line 277) | def actualSource(self, actualSource: str) -> None:
    method moduleDataSource (line 281) | def moduleDataSource(self, moduleDataSource: str) -> None:
    method asDict (line 284) | def asDict(self) -> dict:

FILE: spiderfoot/helpers.py
  class _GraphNode (line 23) | class _GraphNode(typing.TypedDict):
  class _GraphEdge (line 31) | class _GraphEdge(typing.TypedDict):
  class _Graph (line 36) | class _Graph(typing.TypedDict, total=False):
  class Tree (line 40) | class Tree(typing.TypedDict):
  class ExtractedLink (line 44) | class ExtractedLink(typing.TypedDict):
  class SpiderFootHelpers (line 68) | class SpiderFootHelpers():
    method dataPath (line 79) | def dataPath() -> str:
    method cachePath (line 93) | def cachePath() -> str:
    method logPath (line 107) | def logPath() -> str:
    method loadModulesAsDict (line 121) | def loadModulesAsDict(path: str, ignore_files: typing.Optional[typing....
    method loadCorrelationRulesRaw (line 175) | def loadCorrelationRulesRaw(path: str, ignore_files: typing.Optional[t...
    method targetTypeFromString (line 212) | def targetTypeFromString(target: str) -> typing.Optional[str]:
    method urlRelativeToAbsolute (line 248) | def urlRelativeToAbsolute(url: str) -> typing.Optional[str]:
    method urlBaseDir (line 286) | def urlBaseDir(url: str) -> typing.Optional[str]:
    method urlBaseUrl (line 316) | def urlBaseUrl(url: str) -> typing.Optional[str]:
    method dictionaryWordsFromWordlists (line 344) | def dictionaryWordsFromWordlists(wordlists: typing.Optional[typing.Lis...
    method humanNamesFromWordlists (line 372) | def humanNamesFromWordlists(wordlists: typing.Optional[typing.List[str...
    method usernamesFromWordlists (line 400) | def usernamesFromWordlists(wordlists: typing.Optional[typing.List[str]...
    method buildGraphGexf (line 428) | def buildGraphGexf(root: str, title: str, data: typing.List[str], flt:...
    method buildGraphJson (line 484) | def buildGraphJson(root: str, data: typing.List[str], flt: typing.Opti...
    method buildGraphData (line 559) | def buildGraphData(data: typing.List[str], flt: typing.Optional[typing...
    method dataParentChildToTree (line 636) | def dataParentChildToTree(data: typing.Dict[str, typing.Optional[typin...
    method validLEI (line 693) | def validLEI(lei: str) -> bool:
    method validEmail (line 715) | def validEmail(email: str) -> bool:
    method validPhoneNumber (line 747) | def validPhoneNumber(phone: str) -> bool:
    method genScanInstanceId (line 765) | def genScanInstanceId() -> str:
    method extractLinksFromHtml (line 774) | def extractLinksFromHtml(url: str, data: str, domains: typing.Optional...
    method extractHashesFromText (line 894) | def extractHashesFromText(data: str) -> typing.List[typing.Tuple[str, ...
    method extractUrlsFromRobotsTxt (line 923) | def extractUrlsFromRobotsTxt(robotsTxtData: str) -> typing.List[str]:
    method extractPgpKeysFromText (line 951) | def extractPgpKeysFromText(data: str) -> typing.List[str]:
    method extractEmailsFromText (line 973) | def extractEmailsFromText(data: str) -> typing.List[str]:
    method extractIbansFromText (line 995) | def extractIbansFromText(data: str) -> typing.List[str]:
    method extractCreditCardsFromText (line 1077) | def extractCreditCardsFromText(data: str) -> typing.List[str]:
    method extractUrlsFromText (line 1127) | def extractUrlsFromText(content: str) -> typing.List[str]:
    method sslDerToPem (line 1143) | def sslDerToPem(der_cert: bytes) -> str:
    method countryNameFromCountryCode (line 1161) | def countryNameFromCountryCode(countryCode: str) -> typing.Optional[str]:
    method countryNameFromTld (line 1176) | def countryNameFromTld(tld: str) -> typing.Optional[str]:
    method countryCodes (line 1210) | def countryCodes() -> typing.Dict[str, str]:
    method sanitiseInput (line 1478) | def sanitiseInput(cmd: str, extra: typing.Optional[typing.List[str]] =...

FILE: spiderfoot/logger.py
  class SpiderFootSqliteLogHandler (line 11) | class SpiderFootSqliteLogHandler(logging.Handler):
    method __init__ (line 18) | def __init__(self, opts: dict) -> None:
    method emit (line 34) | def emit(self, record: 'logging.LogRecord') -> None:
    method logBatch (line 51) | def logBatch(self):
    method makeDbh (line 63) | def makeDbh(self) -> None:
  function logListenerSetup (line 68) | def logListenerSetup(loggingQueue, opts: dict = None) -> 'logging.handle...
  function logWorkerSetup (line 136) | def logWorkerSetup(loggingQueue) -> 'logging.Logger':
  function stop_listener (line 154) | def stop_listener(listener: 'logging.handlers.QueueListener') -> None:

FILE: spiderfoot/plugin.py
  class SpiderFootPluginLogger (line 26) | class SpiderFootPluginLogger(logging.Logger):
    method findCaller (line 33) | def findCaller(self, stack_info: bool = False, stacklevel: int = 1) ->...
  class SpiderFootPlugin (line 78) | class SpiderFootPlugin():
    method __init__ (line 135) | def __init__(self) -> None:
    method log (line 144) | def log(self):
    method _updateSocket (line 151) | def _updateSocket(self, socksProxy: str) -> None:
    method clearListeners (line 160) | def clearListeners(self) -> None:
    method setup (line 167) | def setup(self, sf, userOpts: dict = {}) -> None:
    method debug (line 176) | def debug(self, *args, **kwargs) -> None:
    method info (line 186) | def info(self, *args, **kwargs) -> None:
    method error (line 196) | def error(self, *args, **kwargs) -> None:
    method enrichTarget (line 206) | def enrichTarget(self, target: str) -> None:
    method setTarget (line 216) | def setTarget(self, target) -> None:
    method setDbh (line 232) | def setDbh(self, dbh) -> None:
    method setScanId (line 241) | def setScanId(self, scanId: str) -> None:
    method getScanId (line 255) | def getScanId(self) -> str:
    method getTarget (line 269) | def getTarget(self) -> str:
    method registerListener (line 283) | def registerListener(self, listener) -> None:
    method setOutputFilter (line 293) | def setOutputFilter(self, types) -> None:
    method tempStorage (line 296) | def tempStorage(self) -> dict:
    method notifyListeners (line 312) | def notifyListeners(self, sfEvent) -> None:
    method checkForStop (line 399) | def checkForStop(self) -> bool:
    method running (line 429) | def running(self) -> bool:
    method watchedEvents (line 438) | def watchedEvents(self) -> list:
    method producedEvents (line 451) | def producedEvents(self) -> list:
    method handleEvent (line 462) | def handleEvent(self, sfEvent) -> None:
    method asdict (line 472) | def asdict(self) -> dict:
    method start (line 486) | def start(self) -> None:
    method finish (line 490) | def finish(self):
    method threadWorker (line 498) | def threadWorker(self) -> None:
    method poolExecute (line 541) | def poolExecute(self, callback, *args, **kwargs) -> None:
    method threadPool (line 556) | def threadPool(self, *args, **kwargs):
    method setSharedThreadPool (line 559) | def setSharedThreadPool(self, sharedThreadPool) -> None:

FILE: spiderfoot/static/js/spiderfoot.newscan.js
  function submitForm (line 4) | function submitForm() {
  function switchTab (line 20) | function switchTab(tabname) {
  function selectAll (line 33) | function selectAll() {
  function deselectAll (line 37) | function deselectAll() {

FILE: spiderfoot/static/js/spiderfoot.opts.js
  function saveSettings (line 2) | function saveSettings() {
  function clearSettings (line 11) | function clearSettings() {
  function switchTab (line 15) | function switchTab(tab) {
  function getFile (line 23) | function getFile(elemId) {

FILE: spiderfoot/static/js/spiderfoot.scanlist.js
  function switchSelectAll (line 5) | function switchSelectAll() {
  function filter (line 13) | function filter(type) {
  function getSelected (line 32) | function getSelected() {
  function stopScan (line 46) | function stopScan(id) {
  function stopSelected (line 53) | function stopSelected() {
  function deleteScan (line 66) | function deleteScan(id) {
  function deleteSelected (line 73) | function deleteSelected() {
  function rerunSelected (line 86) | function rerunSelected() {
  function exportSelected (line 97) | function exportSelected(type) {
  function reload (line 130) | function reload() {
  function showlist (line 136) | function showlist(types, filter) {
  function showlisttable (line 154) | function showlisttable(types, filter, data) {

FILE: spiderfoot/static/js/viz.js
  function sf_viz_countTailNodes (line 4) | function sf_viz_countTailNodes(arg) {
  function sf_viz_countTotalNodes (line 24) | function sf_viz_countTotalNodes(arg) {
  function sf_viz_countLevels (line 44) | function sf_viz_countLevels(arg, levelsDeep, maxLevels) {
  function sf_viz_vbar (line 74) | function sf_viz_vbar(targetId, gdata) {
  function sf_viz_vbar_type (line 177) | function sf_viz_vbar_type(d) {
  function sf_viz_dendrogram (line 182) | function sf_viz_dendrogram(targetId, data) {
  function sf_viz_bubble (line 283) | function sf_viz_bubble(targetId, plotData) {

FILE: spiderfoot/target.py
  class SpiderFootTarget (line 13) | class SpiderFootTarget():
    method __init__ (line 30) | def __init__(self, targetValue: str, typeName: str) -> None:
    method targetType (line 42) | def targetType(self) -> str:
    method targetType (line 46) | def targetType(self, targetType: str) -> None:
    method targetValue (line 56) | def targetValue(self) -> str:
    method targetValue (line 60) | def targetValue(self, targetValue: str) -> None:
    method targetAliases (line 69) | def targetAliases(self) -> typing.List[TargetAlias]:
    method targetAliases (line 73) | def targetAliases(self, value: typing.List[TargetAlias]) -> None:
    method setAlias (line 76) | def setAlias(self, value: str, typeName: str) -> None:
    method _getEquivalents (line 107) | def _getEquivalents(self, typeName: str) -> typing.List[str]:
    method getNames (line 122) | def getNames(self) -> typing.List[str]:
    method getAddresses (line 141) | def getAddresses(self) -> typing.List[str]:
    method matches (line 157) | def matches(self, value: str, includeParents: bool = False, includeChi...

FILE: spiderfoot/threadpool.py
  class SpiderFootThreadPool (line 8) | class SpiderFootThreadPool:
    method __init__ (line 34) | def __init__(self, threads: int = 100, qsize: int = 10, name: str = ''...
    method start (line 53) | def start(self) -> None:
    method stop (line 61) | def stop(self) -> bool:
    method stop (line 65) | def stop(self, val: bool):
    method shutdown (line 72) | def shutdown(self, wait: bool = True) -> dict:
    method submit (line 117) | def submit(self, callback, *args, **kwargs) -> None:
    method countQueuedTasks (line 135) | def countQueuedTasks(self, taskName: str) -> int:
    method inputQueue (line 155) | def inputQueue(self, taskName: str = "default") -> str:
    method outputQueue (line 162) | def outputQueue(self, taskName: str = "default") -> str:
    method map (line 169) | def map(self, callback, iterable, *args, **kwargs) -> None:  # noqa: A003
    method results (line 188) | def results(self, taskName: str = "default", wait: bool = False) -> None:
    method feedQueue (line 201) | def feedQueue(self, callback, iterable, args, kwargs) -> None:
    method finished (line 208) | def finished(self):
    method __enter__ (line 221) | def __enter__(self):
    method __exit__ (line 224) | def __exit__(self, exception_type, exception_value, traceback):
  class ThreadPoolWorker (line 228) | class ThreadPoolWorker(threading.Thread):
    method __init__ (line 230) | def __init__(self, pool, name: str = None) -> None:
    method run (line 240) | def run(self) -> None:

FILE: test/conftest.py
  function default_options (line 6) | def default_options(request):

FILE: test/integration/modules/test_sfp__stor_db.py
  class TestModuleIntegration_stor_db (line 10) | class TestModuleIntegration_stor_db(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp__stor_stdout.py
  class TestModuleIntegration_stor_stdout (line 10) | class TestModuleIntegration_stor_stdout(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_abstractapi.py
  class TestModuleIntegrationAbstractapi (line 10) | class TestModuleIntegrationAbstractapi(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_abusech.py
  class TestModuleIntegrationAbusech (line 10) | class TestModuleIntegrationAbusech(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_abuseipdb.py
  class TestModuleIntegrationabuseipdb (line 10) | class TestModuleIntegrationabuseipdb(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_abusix.py
  class TestModuleIntegrationAbusix (line 10) | class TestModuleIntegrationAbusix(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_accounts.py
  class TestModuleIntegrationaccounts (line 10) | class TestModuleIntegrationaccounts(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_adblock.py
  class TestModuleIntegrationAdblock (line 10) | class TestModuleIntegrationAdblock(unittest.TestCase):
    method test_handleEvent_event_data_provider_javascript_url_matching_ad_filter_should_return_event (line 12) | def test_handleEvent_event_data_provider_javascript_url_matching_ad_fi...
    method test_handleEvent_event_data_external_url_matching_ad_filter_should_return_event (line 54) | def test_handleEvent_event_data_external_url_matching_ad_filter_should...
    method test_handleEvent_event_data_external_url_not_matching_ad_filter_should_not_return_event (line 96) | def test_handleEvent_event_data_external_url_not_matching_ad_filter_sh...

FILE: test/integration/modules/test_sfp_adguard_dns.py
  class TestModuleIntegrationAdGuardDns (line 10) | class TestModuleIntegrationAdGuardDns(unittest.TestCase):
    method test_handleEvent_event_data_adult_internet_name_blocked_should_return_event (line 12) | def test_handleEvent_event_data_adult_internet_name_blocked_should_ret...
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 54) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...

FILE: test/integration/modules/test_sfp_ahmia.py
  class TestModuleIntegrationAhmia (line 10) | class TestModuleIntegrationAhmia(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_alienvault.py
  class TestModuleIntegrationalienvault (line 10) | class TestModuleIntegrationalienvault(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_alienvaultiprep.py
  class TestModuleIntegrationAlienvaultiprep (line 10) | class TestModuleIntegrationAlienvaultiprep(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_apple_itunes.py
  class TestModuleIntegrationAppleItunes (line 10) | class TestModuleIntegrationAppleItunes(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_archiveorg.py
  class TestModuleIntegrationarchiveorg (line 10) | class TestModuleIntegrationarchiveorg(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_arin.py
  class TestModuleIntegrationarin (line 10) | class TestModuleIntegrationarin(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_azureblobstorage.py
  class TestModuleIntegrationazureblobstorage (line 10) | class TestModuleIntegrationazureblobstorage(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_bgpview.py
  class TestModuleIntegrationBgpview (line 10) | class TestModuleIntegrationBgpview(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_binaryedge.py
  class TestModuleIntegrationBinaryedge (line 10) | class TestModuleIntegrationBinaryedge(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_bingsearch.py
  class TestModuleIntegrationbingsearch (line 10) | class TestModuleIntegrationbingsearch(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_bingsharedip.py
  class TestModuleIntegrationbingsharedip (line 10) | class TestModuleIntegrationbingsharedip(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_bitcoinabuse.py
  class TestModuleIntegrationBitcoinAbuse (line 10) | class TestModuleIntegrationBitcoinAbuse(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_bitcoinwhoswho.py
  class TestModuleIntegrationBitcoinwhoswho (line 10) | class TestModuleIntegrationBitcoinwhoswho(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_blockchain.py
  class TestModuleIntegrationBlockchain (line 10) | class TestModuleIntegrationBlockchain(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_blocklistde.py
  class TestModuleIntegrationBlocklistde (line 10) | class TestModuleIntegrationBlocklistde(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_botscout.py
  class TestModuleIntegrationBotscout (line 10) | class TestModuleIntegrationBotscout(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_botvrij.py
  class TestModuleIntegrationBotvrij (line 10) | class TestModuleIntegrationBotvrij(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_builtwith.py
  class TestModuleIntegrationBuiltwith (line 10) | class TestModuleIntegrationBuiltwith(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_c99.py
  class TestModuleIntegrationC99 (line 10) | class TestModuleIntegrationC99(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_callername.py
  class TestModuleIntegrationcallername (line 10) | class TestModuleIntegrationcallername(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_censys.py
  class TestModuleIntegrationCensys (line 10) | class TestModuleIntegrationCensys(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_certspotter.py
  class TestModuleIntegrationCertspotter (line 10) | class TestModuleIntegrationCertspotter(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_cinsscore.py
  class TestModuleIntegrationCinsscore (line 10) | class TestModuleIntegrationCinsscore(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_circllu.py
  class TestModuleIntegrationCircllu (line 10) | class TestModuleIntegrationCircllu(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_citadel.py
  class TestModuleIntegrationcitadel (line 10) | class TestModuleIntegrationcitadel(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_cleanbrowsing.py
  class TestModuleIntegrationcleanbrowsing (line 10) | class TestModuleIntegrationcleanbrowsing(unittest.TestCase):
    method test_handleEvent_event_data_adult_internet_name_blocked_should_return_event (line 12) | def test_handleEvent_event_data_adult_internet_name_blocked_should_ret...
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 54) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...

FILE: test/integration/modules/test_sfp_cleantalk.py
  class TestModuleIntegrationcleantalk (line 10) | class TestModuleIntegrationcleantalk(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_clearbit.py
  class TestModuleIntegrationclearbit (line 10) | class TestModuleIntegrationclearbit(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_cloudflaredns.py
  class TestModuleIntegrationCloudflaredns (line 10) | class TestModuleIntegrationCloudflaredns(unittest.TestCase):
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...
    method test_handleEvent_event_data_adult_internet_name_blocked_should_return_event (line 44) | def test_handleEvent_event_data_adult_internet_name_blocked_should_ret...

FILE: test/integration/modules/test_sfp_coinblocker.py
  class TestModuleIntegrationCoinblocker (line 10) | class TestModuleIntegrationCoinblocker(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_commoncrawl.py
  class TestModuleIntegrationcommoncrawl (line 10) | class TestModuleIntegrationcommoncrawl(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_comodo.py
  class TestModuleIntegrationcomodo (line 10) | class TestModuleIntegrationcomodo(unittest.TestCase):
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...

FILE: test/integration/modules/test_sfp_crobat_api.py
  class TestModuleIntegrationCrobat_api (line 10) | class TestModuleIntegrationCrobat_api(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_crossref.py
  class TestModuleIntegrationCrossref (line 10) | class TestModuleIntegrationCrossref(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_crt.py
  class TestModuleIntegrationCrt (line 10) | class TestModuleIntegrationCrt(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_crxcavator.py
  class TestModuleIntegrationCrxcavator (line 10) | class TestModuleIntegrationCrxcavator(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_customfeed.py
  class TestModuleIntegrationCustomfeed (line 10) | class TestModuleIntegrationCustomfeed(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_cybercrimetracker.py
  class TestModuleIntegrationCybercrimetracker (line 10) | class TestModuleIntegrationCybercrimetracker(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_debounce.py
  class TestModuleIntegrationDebounce (line 10) | class TestModuleIntegrationDebounce(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dehashed.py
  class TestModuleIntegrationDehashed (line 10) | class TestModuleIntegrationDehashed(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_digitaloceanspace.py
  class TestModuleIntegrationDigitaloceanspace (line 10) | class TestModuleIntegrationDigitaloceanspace(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dns_for_family.py
  class TestModuleIntegrationDnsForFamily (line 10) | class TestModuleIntegrationDnsForFamily(unittest.TestCase):
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...
    method test_handleEvent_event_data_adult_internet_name_blocked_should_return_event (line 44) | def test_handleEvent_event_data_adult_internet_name_blocked_should_ret...

FILE: test/integration/modules/test_sfp_dnsbrute.py
  class TestModuleIntegrationDnsBrute (line 10) | class TestModuleIntegrationDnsBrute(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnscommonsrv.py
  class TestModuleIntegrationDnsCommonsrv (line 10) | class TestModuleIntegrationDnsCommonsrv(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnsdb.py
  class TestModuleIntegrationdnsdb (line 10) | class TestModuleIntegrationdnsdb(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnsdumpster.py
  class TestModuleIntegrationDnsDumpster (line 10) | class TestModuleIntegrationDnsDumpster(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnsgrep.py
  class TestModuleIntegrationDnsgrep (line 10) | class TestModuleIntegrationDnsgrep(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnsneighbor.py
  class TestModuleIntegrationDnsneighbor (line 10) | class TestModuleIntegrationDnsneighbor(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnsraw.py
  class TestModuleIntegrationdnsraw (line 10) | class TestModuleIntegrationdnsraw(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dnsresolve.py
  class TestModuleIntegrationDnsResolve (line 10) | class TestModuleIntegrationDnsResolve(unittest.TestCase):
    method test_enrichTarget_should_return_SpiderFootTarget (line 12) | def test_enrichTarget_should_return_SpiderFootTarget(self):
    method test_resolveTargets_should_return_list (line 27) | def test_resolveTargets_should_return_list(self):
    method test_handleEvent_event_data_ip_address_should_return_internet_name_event (line 65) | def test_handleEvent_event_data_ip_address_should_return_internet_name...
    method test_handleEvent_event_data_ipv6_address_should_return_internet_name_event (line 107) | def test_handleEvent_event_data_ipv6_address_should_return_internet_na...
    method test_handleEvent_event_data_affiliate_ip_address_should_return_affiliate_internet_name_event (line 149) | def test_handleEvent_event_data_affiliate_ip_address_should_return_aff...
    method test_handleEvent_event_data_raw_rir_data_containing_subdomain_should_return_internet_name_event (line 190) | def test_handleEvent_event_data_raw_rir_data_containing_subdomain_shou...

FILE: test/integration/modules/test_sfp_dnszonexfer.py
  class TestModuleIntegrationDnsZoneXfer (line 10) | class TestModuleIntegrationDnsZoneXfer(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_dronebl.py
  class TestModuleIntegrationDronebl (line 10) | class TestModuleIntegrationDronebl(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_duckduckgo.py
  class TestModuleIntegrationDuckduckgo (line 10) | class TestModuleIntegrationDuckduckgo(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_email.py
  class TestModuleIntegrationEmail (line 10) | class TestModuleIntegrationEmail(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_emailcrawlr.py
  class TestModuleIntegrationemailcrawlr (line 10) | class TestModuleIntegrationemailcrawlr(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_emailformat.py
  class TestModuleIntegrationEmailFormat (line 10) | class TestModuleIntegrationEmailFormat(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_emailrep.py
  class TestModuleIntegrationEmailrep (line 10) | class TestModuleIntegrationEmailrep(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_emergingthreats.py
  class TestModuleIntegrationEmergingthreats (line 10) | class TestModuleIntegrationEmergingthreats(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_etherscan.py
  class TestModuleIntegrationEtherscan (line 10) | class TestModuleIntegrationEtherscan(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_filemeta.py
  class TestModuleIntegrationFilemeta (line 10) | class TestModuleIntegrationFilemeta(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_flickr.py
  class TestModuleIntegrationFlickr (line 10) | class TestModuleIntegrationFlickr(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_focsec.py
  class TestModuleIntegrationFocsec (line 10) | class TestModuleIntegrationFocsec(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_fortinet.py
  class TestModuleIntegrationFortinet (line 10) | class TestModuleIntegrationFortinet(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_fraudguard.py
  class TestModuleIntegrationFraudguard (line 10) | class TestModuleIntegrationFraudguard(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_fsecure_riddler.py
  class TestModuleIntegrationFsecureRiddler (line 10) | class TestModuleIntegrationFsecureRiddler(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_fullcontact.py
  class TestModuleIntegrationFullContact (line 10) | class TestModuleIntegrationFullContact(unittest.TestCase):
    method test_handleEvent (line 12) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_fullhunt.py
  class TestModuleIntegrationFullhunt (line 10) | class TestModuleIntegrationFullhunt(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_github.py
  class TestModuleIntegrationGithub (line 10) | class TestModuleIntegrationGithub(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_gleif.py
  class TestModuleIntegrationGleif (line 10) | class TestModuleIntegrationGleif(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_google_tag_manager.py
  class TestModuleIntegrationGoogleTagManager (line 10) | class TestModuleIntegrationGoogleTagManager(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_googlemaps.py
  class TestModuleIntegrationGoogleMaps (line 10) | class TestModuleIntegrationGoogleMaps(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_googleobjectstorage.py
  class TestModuleIntegrationGoogleObjectStorage (line 10) | class TestModuleIntegrationGoogleObjectStorage(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_googlesafebrowsing.py
  class TestModuleIntegrationGoogleSafebrowsing (line 10) | class TestModuleIntegrationGoogleSafebrowsing(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_googlesearch.py
  class TestModuleIntegrationGoogleSearch (line 10) | class TestModuleIntegrationGoogleSearch(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_gravatar.py
  class TestModuleIntegrationGravatar (line 10) | class TestModuleIntegrationGravatar(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_grayhatwarfare.py
  class TestModuleIntegrationGrayhatWarfare (line 10) | class TestModuleIntegrationGrayhatWarfare(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_greensnow.py
  class TestModuleIntegrationgreensnow (line 10) | class TestModuleIntegrationgreensnow(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_grep_app.py
  class TestModuleIntegrationGrepApp (line 10) | class TestModuleIntegrationGrepApp(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_greynoise.py
  class TestModuleIntegrationGreynoise (line 10) | class TestModuleIntegrationGreynoise(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_h1nobbdde.py
  class TestModuleIntegrationH1nobbdde (line 10) | class TestModuleIntegrationH1nobbdde(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_hackertarget.py
  class TestModuleIntegrationHackertarget (line 10) | class TestModuleIntegrationHackertarget(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_haveibeenpwned.py
  class TestModuleIntegrationHaveibeenpwned (line 10) | class TestModuleIntegrationHaveibeenpwned(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_honeypot.py
  class TestModuleIntegrationHoneypot (line 10) | class TestModuleIntegrationHoneypot(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_hosting.py
  class TestModuleIntegrationHosting (line 10) | class TestModuleIntegrationHosting(unittest.TestCase):
    method test_handleEvent_event_data_ip_address_hosted_should_return_event (line 13) | def test_handleEvent_event_data_ip_address_hosted_should_return_event(...
    method test_handleEvent_event_data_ip_address_not_hosted_should_not_return_event (line 50) | def test_handleEvent_event_data_ip_address_not_hosted_should_not_retur...

FILE: test/integration/modules/test_sfp_hostio.py
  class TestModuleIntegrationHostio (line 10) | class TestModuleIntegrationHostio(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_hunter.py
  class TestModuleIntegrationHunter (line 10) | class TestModuleIntegrationHunter(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_hybrid_analysis.py
  class TestModuleIntegrationHybridAnalysis (line 10) | class TestModuleIntegrationHybridAnalysis(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_iknowwhatyoudownload.py
  class TestModuleIntegrationIknowwhatyoudownload (line 10) | class TestModuleIntegrationIknowwhatyoudownload(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_intelx.py
  class TestModuleIntegrationIntelx (line 10) | class TestModuleIntegrationIntelx(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ipapico.py
  class TestModuleIntegrationIpapico (line 10) | class TestModuleIntegrationIpapico(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ipapicom.py
  class TestModuleIntegrationIpapicom (line 10) | class TestModuleIntegrationIpapicom(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ipinfo.py
  class TestModuleIntegrationIpinfo (line 10) | class TestModuleIntegrationIpinfo(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ipqualityscore.py
  class TestModuleIntegrationIpqualityscore (line 10) | class TestModuleIntegrationIpqualityscore(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ipregistry.py
  class TestModuleIntegrationIpregistry (line 10) | class TestModuleIntegrationIpregistry(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ipstack.py
  class TestModuleIntegrationIpstack (line 10) | class TestModuleIntegrationIpstack(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_isc.py
  class TestModuleIntegrationIsc (line 10) | class TestModuleIntegrationIsc(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_jsonwhoiscom.py
  class TestModuleIntegrationJsonwhoiscom (line 10) | class TestModuleIntegrationJsonwhoiscom(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_junkfiles.py
  class TestModuleIntegrationJunkfiles (line 10) | class TestModuleIntegrationJunkfiles(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_keybase.py
  class TestModuleIntegrationKeybase (line 10) | class TestModuleIntegrationKeybase(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_koodous.py
  class TestModuleIntegrationKoodous (line 10) | class TestModuleIntegrationKoodous(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_leakix.py
  class TestModuleIntegrationleakix (line 10) | class TestModuleIntegrationleakix(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_maltiverse.py
  class TestModuleIntegrationMaltiverse (line 10) | class TestModuleIntegrationMaltiverse(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_malwarepatrol.py
  class TestModuleIntegrationMalwarepatrol (line 10) | class TestModuleIntegrationMalwarepatrol(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_metadefender.py
  class TestModuleIntegrationMetadefender (line 10) | class TestModuleIntegrationMetadefender(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_mnemonic.py
  class TestModuleIntegrationMnemonic (line 10) | class TestModuleIntegrationMnemonic(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_multiproxy.py
  class TestModuleIntegrationMultiproxy (line 10) | class TestModuleIntegrationMultiproxy(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_myspace.py
  class TestModuleIntegrationMyspace (line 10) | class TestModuleIntegrationMyspace(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_nameapi.py
  class TestModuleIntegrationNameapi (line 10) | class TestModuleIntegrationNameapi(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_networksdb.py
  class TestModuleIntegrationNetworksdb (line 10) | class TestModuleIntegrationNetworksdb(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_neutrinoapi.py
  class TestModuleIntegrationNeutrinoapi (line 10) | class TestModuleIntegrationNeutrinoapi(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_numverify.py
  class TestModuleIntegrationNumverify (line 10) | class TestModuleIntegrationNumverify(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_onioncity.py
  class TestModuleIntegrationOnioncity (line 10) | class TestModuleIntegrationOnioncity(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_onionsearchengine.py
  class TestModuleIntegrationOnionsearchengine (line 10) | class TestModuleIntegrationOnionsearchengine(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_onyphe.py
  class TestModuleIntegrationOnyphe (line 10) | class TestModuleIntegrationOnyphe(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_openbugbounty.py
  class TestModuleIntegrationOpenbugbounty (line 10) | class TestModuleIntegrationOpenbugbounty(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_opencorporates.py
  class TestModuleIntegrationOpencorporates (line 10) | class TestModuleIntegrationOpencorporates(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_opendns.py
  class TestModuleIntegrationOpendns (line 10) | class TestModuleIntegrationOpendns(unittest.TestCase):
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...
    method test_handleEvent_event_data_adult_internet_name_blocked_should_return_event (line 44) | def test_handleEvent_event_data_adult_internet_name_blocked_should_ret...

FILE: test/integration/modules/test_sfp_opennic.py
  class TestModuleIntegrationOpenNic (line 10) | class TestModuleIntegrationOpenNic(unittest.TestCase):
    method test_handleEvent_event_data_internet_name_with_opennic_tld_should_return_ip_address_event (line 12) | def test_handleEvent_event_data_internet_name_with_opennic_tld_should_...

FILE: test/integration/modules/test_sfp_openphish.py
  class TestModuleIntegrationOpenphish (line 10) | class TestModuleIntegrationOpenphish(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_openstreetmap.py
  class TestModuleIntegrationOpenstreetmap (line 10) | class TestModuleIntegrationOpenstreetmap(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_pageinfo.py
  class TestModuleIntegrationPageInfo (line 10) | class TestModuleIntegrationPageInfo(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_pastebin.py
  class TestModuleIntegrationPastebin (line 10) | class TestModuleIntegrationPastebin(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_pgp.py
  class TestModuleIntegrationPgp (line 10) | class TestModuleIntegrationPgp(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_phishstats.py
  class TestModuleIntegrationPhishstats (line 10) | class TestModuleIntegrationPhishstats(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_phishtank.py
  class TestModuleIntegrationPhishtank (line 10) | class TestModuleIntegrationPhishtank(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_portscan_tcp.py
  class TestModuleIntegrationPortscanTcp (line 10) | class TestModuleIntegrationPortscanTcp(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_projectdiscovery.py
  class TestModuleIntegrationProjectdiscovery (line 9) | class TestModuleIntegrationProjectdiscovery(unittest.TestCase):
    method test_handleEvent (line 12) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_psbdmp.py
  class TestModuleIntegrationPsbdmp (line 10) | class TestModuleIntegrationPsbdmp(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_pulsedive.py
  class TestModuleIntegrationPulsedive (line 10) | class TestModuleIntegrationPulsedive(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_punkspider.py
  class TestModuleIntegrationPunkspider (line 10) | class TestModuleIntegrationPunkspider(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_quad9.py
  class TestModuleIntegrationQuad9 (line 10) | class TestModuleIntegrationQuad9(unittest.TestCase):
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...

FILE: test/integration/modules/test_sfp_reversewhois.py
  class TestModuleIntegrationReversewhois (line 10) | class TestModuleIntegrationReversewhois(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_ripe.py
  class TestModuleIntegrationRipe (line 10) | class TestModuleIntegrationRipe(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_riskiq.py
  class TestModuleIntegrationRiskiq (line 10) | class TestModuleIntegrationRiskiq(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_robtex.py
  class TestModuleIntegrationRobtex (line 10) | class TestModuleIntegrationRobtex(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_s3bucket.py
  class TestModuleIntegrationS3bucket (line 10) | class TestModuleIntegrationS3bucket(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_searchcode.py
  class TestModuleIntegrationCodesearch (line 10) | class TestModuleIntegrationCodesearch(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_securitytrails.py
  class TestModuleIntegrationSecuritytrails (line 10) | class TestModuleIntegrationSecuritytrails(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_seon.py
  class TestModuleIntegrationseon (line 10) | class TestModuleIntegrationseon(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_shodan.py
  class TestModuleIntegrationShodan (line 10) | class TestModuleIntegrationShodan(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_similar.py
  class TestModuleIntegrationSimilar (line 10) | class TestModuleIntegrationSimilar(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_skymem.py
  class TestModuleIntegrationSkymem (line 10) | class TestModuleIntegrationSkymem(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_slideshare.py
  class TestModuleIntegrationSlideshare (line 10) | class TestModuleIntegrationSlideshare(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_snov.py
  class TestModuleIntegrationSnov (line 10) | class TestModuleIntegrationSnov(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_sociallinks.py
  class TestModuleIntegrationsociallinks (line 10) | class TestModuleIntegrationsociallinks(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_socialprofiles.py
  class TestModuleIntegrationSocialprofiles (line 10) | class TestModuleIntegrationSocialprofiles(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_sorbs.py
  class TestModuleIntegrationSorbs (line 10) | class TestModuleIntegrationSorbs(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_spamcop.py
  class TestModuleIntegrationSpamcop (line 10) | class TestModuleIntegrationSpamcop(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_spamhaus.py
  class TestModuleIntegrationSpamhaus (line 10) | class TestModuleIntegrationSpamhaus(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_spider.py
  class TestModuleIntegrationSpider (line 10) | class TestModuleIntegrationSpider(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_spur.py
  class TestModuleIntegrationSpur (line 10) | class TestModuleIntegrationSpur(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_spyonweb.py
  class TestModuleIntegrationSpyonweb (line 10) | class TestModuleIntegrationSpyonweb(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_sslcert.py
  class TestModuleIntegrationSslCert (line 10) | class TestModuleIntegrationSslCert(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_stackoverflow.py
  class TestModuleIntegrationStackoverflow (line 10) | class TestModuleIntegrationStackoverflow(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_stevenblack_hosts.py
  class TestModuleIntegrationStevenblackHosts (line 10) | class TestModuleIntegrationStevenblackHosts(unittest.TestCase):
    method test_handleEvent_event_data_affiliate_internet_name_matching_ad_server_should_return_event (line 12) | def test_handleEvent_event_data_affiliate_internet_name_matching_ad_se...
    method test_handleEvent_event_data_affiliate_internet_name_not_matching_ad_server_should_not_return_event (line 59) | def test_handleEvent_event_data_affiliate_internet_name_not_matching_a...

FILE: test/integration/modules/test_sfp_subdomain_takeover.py
  class TestModuleIntegrationSubdomainTakeover (line 10) | class TestModuleIntegrationSubdomainTakeover(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_sublist3r.py
  class TestModuleIntegrationSublist3r (line 10) | class TestModuleIntegrationSublist3r(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_surbl.py
  class TestModuleIntegrationSurbl (line 10) | class TestModuleIntegrationSurbl(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_talosintel.py
  class TestModuleIntegrationTalosintel (line 10) | class TestModuleIntegrationTalosintel(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_textmagic.py
  class TestModuleIntegrationTextmagic (line 10) | class TestModuleIntegrationTextmagic(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_threatcrowd.py
  class TestModuleIntegrationThreatcrowd (line 10) | class TestModuleIntegrationThreatcrowd(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_threatfox.py
  class TestModuleIntegrationThreatFox (line 10) | class TestModuleIntegrationThreatFox(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_threatminer.py
  class TestModuleIntegrationThreatminer (line 10) | class TestModuleIntegrationThreatminer(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_tldsearch.py
  class TestModuleIntegrationTldsearch (line 10) | class TestModuleIntegrationTldsearch(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_torch.py
  class TestModuleIntegrationTorch (line 10) | class TestModuleIntegrationTorch(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_torexits.py
  class TestModuleIntegrationTorExits (line 10) | class TestModuleIntegrationTorExits(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_trashpanda.py
  class TestModuleIntegrationTrashpanda (line 10) | class TestModuleIntegrationTrashpanda(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_trumail.py
  class TestModuleIntegrationTrumail (line 10) | class TestModuleIntegrationTrumail(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_twilio.py
  class TestModuleIntegrationTwilio (line 10) | class TestModuleIntegrationTwilio(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_twitter.py
  class TestModuleIntegrationTwitter (line 10) | class TestModuleIntegrationTwitter(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_uceprotect.py
  class TestModuleIntegrationUceprotect (line 10) | class TestModuleIntegrationUceprotect(unittest.TestCase):
    method test_handleEvent_event_data_safe_ip_address_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_ip_address_not_blocked_should_not...

FILE: test/integration/modules/test_sfp_urlscan.py
  class TestModuleIntegrationUrlscan (line 10) | class TestModuleIntegrationUrlscan(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_venmo.py
  class TestModuleIntegrationVenmo (line 10) | class TestModuleIntegrationVenmo(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_viewdns.py
  class TestModuleIntegrationViewdns (line 10) | class TestModuleIntegrationViewdns(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_virustotal.py
  class TestModuleIntegrationVirustotal (line 10) | class TestModuleIntegrationVirustotal(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_voipbl.py
  class TestModuleIntegrationVoipbl (line 10) | class TestModuleIntegrationVoipbl(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_vxvault.py
  class TestModuleIntegrationVxvault (line 10) | class TestModuleIntegrationVxvault(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_webserver.py
  class TestModuleIntegrationWebserver (line 10) | class TestModuleIntegrationWebserver(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_whatcms.py
  class TestModuleIntegrationWhatCMS (line 10) | class TestModuleIntegrationWhatCMS(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_whois.py
  class TestModuleIntegrationwhois (line 10) | class TestModuleIntegrationwhois(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_whoisology.py
  class TestModuleIntegrationWhoisology (line 10) | class TestModuleIntegrationWhoisology(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_whoxy.py
  class TestModuleIntegrationWhoxy (line 10) | class TestModuleIntegrationWhoxy(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_wigle.py
  class TestModuleIntegrationWigle (line 10) | class TestModuleIntegrationWigle(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_wikileaks.py
  class TestModuleIntegrationWikileaks (line 10) | class TestModuleIntegrationWikileaks(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_wikipediaedits.py
  class TestModuleIntegrationWikipediaedits (line 10) | class TestModuleIntegrationWikipediaedits(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_xforce.py
  class TestModuleIntegrationXforce (line 10) | class TestModuleIntegrationXforce(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_yandexdns.py
  class TestModuleIntegrationYandexDns (line 10) | class TestModuleIntegrationYandexDns(unittest.TestCase):
    method test_handleEvent_event_data_safe_internet_name_not_blocked_should_not_return_event (line 12) | def test_handleEvent_event_data_safe_internet_name_not_blocked_should_...
    method test_handleEvent_event_data_adult_internet_name_blocked_should_return_event (line 44) | def test_handleEvent_event_data_adult_internet_name_blocked_should_ret...

FILE: test/integration/modules/test_sfp_zetalytics.py
  class TestModuleIntegrationZetalytics (line 10) | class TestModuleIntegrationZetalytics(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/modules/test_sfp_zoneh.py
  class TestModuleIntegrationZoneh (line 10) | class TestModuleIntegrationZoneh(unittest.TestCase):
    method test_handleEvent (line 13) | def test_handleEvent(self):

FILE: test/integration/test_sf.py
  class TestSf (line 7) | class TestSf(unittest.TestCase):
    method execute (line 38) | def execute(self, command):
    method test_no_args_should_print_arg_l_required (line 47) | def test_no_args_should_print_arg_l_required(self):
    method test_help_arg_should_print_help_and_exit (line 53) | def test_help_arg_should_print_help_and_exit(self):
    method test_modules_arg_should_print_modules_and_exit (line 59) | def test_modules_arg_should_print_modules_and_exit(self):
    method test_types_arg_should_print_types_and_exit (line 64) | def test_types_arg_should_print_types_and_exit(self):
    method test_l_arg_should_start_web_server (line 70) | def test_l_arg_should_start_web_server(self):
    method test_debug_arg_should_enable_and_print_debug_output (line 76) | def test_debug_arg_should_enable_and_print_debug_output(self):
    method test_quiet_arg_should_hide_debug_output (line 82) | def test_quiet_arg_should_hide_debug_output(self):
    method test_run_scan_invalid_target_should_exit (line 87) | def test_run_scan_invalid_target_should_exit(self):
    method test_run_scan_with_modules_no_target_should_exit (line 93) | def test_run_scan_with_modules_no_target_should_exit(self):
    method test_run_scan_with_types_no_target_should_exit (line 98) | def test_run_scan_with_types_no_target_should_exit(self):
    method test_run_scan_with_invalid_module_should_run_scan_and_exit (line 103) | def test_run_scan_with_invalid_module_should_run_scan_and_exit(self):
    method test_run_scan_with_invalid_type_should_exit (line 109) | def test_run_scan_with_invalid_type_should_exit(self):
    method test_run_scan_should_run_scan_and_exit (line 114) | def test_run_scan_should_run_scan_and_exit(self):
    method test_run_scan_should_print_scan_result_and_exit (line 125) | def test_run_scan_should_print_scan_result_and_exit(self):

FILE: test/integration/test_sfcli.py
  class TestSfcli (line 7) | class TestSfcli(unittest.TestCase):
    method execute (line 12) | def execute(self, command):
    method test_help_arg_should_print_help_and_exit (line 21) | def test_help_arg_should_print_help_and_exit(self):

FILE: test/integration/test_sfwebui.py
  class TestSpiderFootWebUiRoutes (line 12) | class TestSpiderFootWebUiRoutes(helper.CPWebCase):
    method setup_server (line 14) | def setup_server():
    method test_invalid_page_returns_404 (line 57) | def test_invalid_page_returns_404(self):
    method test_static_returns_200 (line 61) | def test_static_returns_200(self):
    method test_scaneventresultexport_invalid_scan_id_returns_200 (line 65) | def test_scaneventresultexport_invalid_scan_id_returns_200(self):
    method test_scaneventresultexportmulti (line 69) | def test_scaneventresultexportmulti(self):
    method test_scansearchresultexport (line 73) | def test_scansearchresultexport(self):
    method test_scanexportjsonmulti (line 77) | def test_scanexportjsonmulti(self):
    method test_scanviz (line 81) | def test_scanviz(self):
    method test_scanvizmulti (line 85) | def test_scanvizmulti(self):
    method test_scanopts_invalid_scan_returns_200 (line 89) | def test_scanopts_invalid_scan_returns_200(self):
    method test_rerunscan (line 93) | def test_rerunscan(self):
    method test_rerunscanmulti_invalid_scan_id_returns_200 (line 98) | def test_rerunscanmulti_invalid_scan_id_returns_200(self):
    method test_newscan_returns_200 (line 103) | def test_newscan_returns_200(self):
    method test_clonescan (line 109) | def test_clonescan(self):
    method test_index_returns_200 (line 114) | def test_index_returns_200(self):
    method test_scaninfo_invalid_scan_returns_200 (line 118) | def test_scaninfo_invalid_scan_returns_200(self):
    method test_opts_returns_200 (line 124) | def test_opts_returns_200(self):
    method test_optsexport (line 128) | def test_optsexport(self):
    method test_optsraw (line 136) | def test_optsraw(self):
    method test_scandelete_invalid_scan_id_returns_404 (line 140) | def test_scandelete_invalid_scan_id_returns_404(self):
    method test_savesettings (line 146) | def test_savesettings(self):
    method test_savesettingsraw (line 151) | def test_savesettingsraw(self):
    method test_resultsetfp (line 155) | def test_resultsetfp(self):
    method test_eventtypes (line 160) | def test_eventtypes(self):
    method test_modules (line 165) | def test_modules(self):
    method test_ping_returns_200 (line 170) | def test_ping_returns_200(self):
    method test_query_returns_200 (line 175) | def test_query_returns_200(self):
    method tes
Copy disabled (too large) Download .json
Condensed preview — 795 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (14,876K chars).
[
  {
    "path": ".dockerignore",
    "chars": 129,
    "preview": ".git/\n\nbuild\ndist\n*.egg-info\n*.egg/\n*.pyc\n*.swp\n\nvenv/\ncache/\nlog/\nspiderfoot.db*\nspiderfoot.test.db\n\n__pycache__\nhtmlco"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 386,
    "preview": "Please provide a description of the issue and any relevant error messages.\n\nIf you can provide an application stack trac"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 605,
    "preview": "name: \"CodeQL\"\n\non:\n  push:\n    branches:\n      - master\n  schedule:\n    - cron: \"26 16 * * 0\"\n\njobs:\n  analyze:\n    nam"
  },
  {
    "path": ".github/workflows/tests.yaml",
    "chars": 1094,
    "preview": "name: Tests\n\non:\n  push:\n    branches: master\n  pull_request:\n    branches: master\n\njobs:\n  build:\n\n    runs-on: ${{ mat"
  },
  {
    "path": ".gitignore",
    "chars": 4407,
    "preview": "# SpiderFoot specific #\n#######################\n/cache/\n/log/\n/spiderfoot.db*\npasswd\nspiderfoot.crt\nspiderfoot.key\n\nspid"
  },
  {
    "path": ".pylintrc",
    "chars": 14767,
    "preview": "[MASTER]\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are lo"
  },
  {
    "path": "Dockerfile",
    "chars": 2779,
    "preview": "#\n# Spiderfoot Dockerfile\n#\n# http://www.spiderfoot.net\n#\n# Written by: Michael Pellon <m@pellon.io>\n# Updated by: Chand"
  },
  {
    "path": "Dockerfile.full",
    "chars": 4902,
    "preview": "#\n# Spiderfoot Dockerfile (Full - includes all CLI tools, etc.)\n#\n# http://www.spiderfoot.net\n#\n# Written by: TheTechrom"
  },
  {
    "path": "LICENSE",
    "chars": 1077,
    "preview": "Copyright 2022 Steve Micallef <steve@binarypool.com>\n\nPermission is hereby granted, free of charge, to any person obtain"
  },
  {
    "path": "README.md",
    "chars": 33982,
    "preview": "<a href=\"https://www.spiderfoot.net/r.php?u=aHR0cHM6Ly93d3cuc3BpZGVyZm9vdC5uZXQv&s=os_gh\"><img src=\"https://www.spiderfo"
  },
  {
    "path": "THANKYOU",
    "chars": 2207,
    "preview": "These people are owed some credit for their contributions to SpiderFoot, be it\nbug fixes or new functionality. Thank you"
  },
  {
    "path": "VERSION",
    "chars": 17,
    "preview": "SpiderFoot 4.0.0\n"
  },
  {
    "path": "correlations/README.md",
    "chars": 18491,
    "preview": "## Background\n\nSpiderFoot’s goal is to automate OSINT collection and analysis to the greatest extent possible. Since its"
  },
  {
    "path": "correlations/cert_expired.yaml",
    "chars": 516,
    "preview": "id: cert_expired\nversion: 1\nmeta:\n  name: Expired SSL certificate found\n  description: >\n    A host was found with an ex"
  },
  {
    "path": "correlations/cloud_bucket_open.yaml",
    "chars": 714,
    "preview": "id: cloud_bucket_open\nversion: 1\nmeta:\n  name: Cloud storage bucket open to the Internet\n  description: >\n    A cloud st"
  },
  {
    "path": "correlations/cloud_bucket_open_related.yaml",
    "chars": 773,
    "preview": "id: cloud_bucket_open_related\nversion: 1\nmeta:\n  name: Possibly related cloud storage bucket open to the Internet\n  desc"
  },
  {
    "path": "correlations/data_from_base64.yaml",
    "chars": 603,
    "preview": "id: data_from_base64\nversion: 1\nmeta:\n  name: Data was found within base64-encoded data\n  description: >\n    Possibly in"
  },
  {
    "path": "correlations/data_from_docmeta.yaml",
    "chars": 620,
    "preview": "id: data_from_docmeta\nversion: 1\nmeta:\n  name: Data was found within document/image meta data\n  description: >\n    Possi"
  },
  {
    "path": "correlations/database_exposed.yaml",
    "chars": 1125,
    "preview": "id: database_exposed\nversion: 1\nmeta:\n  name: Database server exposed to the Internet\n  description: >\n    A database te"
  },
  {
    "path": "correlations/dev_or_test_system.yaml",
    "chars": 705,
    "preview": "id: dev_or_test_system\nversion: 1\nmeta:\n  name: A host appearing to be a test or development system was found\n  descript"
  },
  {
    "path": "correlations/dns_zone_transfer_possible.yaml",
    "chars": 546,
    "preview": "id: dns_zone_transfer_possible\nversion: 1\nmeta:\n  name: DNS Zone Transfer is possible\n  description: >\n    It was possib"
  },
  {
    "path": "correlations/egress_ip_from_wikipedia.yaml",
    "chars": 871,
    "preview": "id: egress_ip_from_wikipedia\nversion: 1\nmeta:\n  name: Wikipedia page edit from target-owned network\n  description: >\n   "
  },
  {
    "path": "correlations/email_in_multiple_breaches.yaml",
    "chars": 753,
    "preview": "id: email_in_multiple_breaches\nversion: 1\nmeta:\n  name: >\n    An email address was reported to be in multiple breaches\n "
  },
  {
    "path": "correlations/email_in_whois.yaml",
    "chars": 698,
    "preview": "id: email_in_whois\nversion: 1\nmeta:\n  name: A target-relevant email address was found in Whois data\n  description: >\n   "
  },
  {
    "path": "correlations/email_only_from_pasteleak_site.yaml",
    "chars": 930,
    "preview": "id: email_only_from_pasteleak_site\nversion: 1\nmeta:\n  name: Email address only from paste/leak site\n  description: >\n   "
  },
  {
    "path": "correlations/host_only_from_bruteforce.yaml",
    "chars": 813,
    "preview": "id: host_only_from_bruteforce\nversion: 1\nmeta:\n  name: Host only from bruteforcing\n  description: >\n    A hostname was f"
  },
  {
    "path": "correlations/host_only_from_certificatetransparency.yaml",
    "chars": 966,
    "preview": "id: host_only_from_certificatetransparency\nversion: 1\nmeta:\n  name: Hostname only from certificate transparency\n  descri"
  },
  {
    "path": "correlations/http_errors.yaml",
    "chars": 689,
    "preview": "id: http_errors\nversion: 1\nmeta:\n  name: Multiple HTTP errors found\n  description: >\n    Non-successful HTTP error codes"
  },
  {
    "path": "correlations/human_name_in_whois.yaml",
    "chars": 605,
    "preview": "id: human_name_in_whois\nversion: 1\nmeta:\n  name: A human name was found in Whois data\n  description: >\n    A human name "
  },
  {
    "path": "correlations/internal_host.yaml",
    "chars": 796,
    "preview": "id: internal_host\nversion: 1\nmeta:\n  name: A host resolving to unroutable IPs was found\n  description: >\n    A host that"
  },
  {
    "path": "correlations/multiple_malicious.yaml",
    "chars": 1092,
    "preview": "id: multiple_malicious\nversion: 1\nmeta:\n  name: >\n    An IP, host, subnet or email address was considered malicious by\n "
  },
  {
    "path": "correlations/multiple_malicious_affiliate.yaml",
    "chars": 1059,
    "preview": "id: multiple_malicious_affiliate\nversion: 1\nmeta:\n  name: >\n    An affiliated IP or host was considered malicious by mul"
  },
  {
    "path": "correlations/multiple_malicious_cohost.yaml",
    "chars": 1028,
    "preview": "id: multiple_malicious_cohost\nversion: 1\nmeta:\n  name: >\n    A co-hosted site was considered malicious by multiple sourc"
  },
  {
    "path": "correlations/name_only_from_pasteleak_site.yaml",
    "chars": 915,
    "preview": "id: name_only_from_pasteleak_site\nversion: 1\nmeta:\n  name: Human name only from paste/leak site\n  description: >\n    A h"
  },
  {
    "path": "correlations/open_port_version.yaml",
    "chars": 678,
    "preview": "id: open_port_version\nversion: 1\nmeta:\n  name: Open TCP port reveals version\n  description: >\n    A possible software ve"
  },
  {
    "path": "correlations/outlier_cloud.yaml",
    "chars": 627,
    "preview": "id: outlier_cloud\nversion: 1\nmeta:\n  name: Outlier Cloud provider\n  description: >\n    A cloud provider that appeared in"
  },
  {
    "path": "correlations/outlier_country.yaml",
    "chars": 467,
    "preview": "id: outlier_country\nversion: 1\nmeta:\n  name: Outlier country\n  description: >\n    A country that appeared in 10% or less"
  },
  {
    "path": "correlations/outlier_email.yaml",
    "chars": 493,
    "preview": "id: outlier_email\nversion: 1\nmeta:\n  name: Outlier email address found\n  description: >\n    An email address that appear"
  },
  {
    "path": "correlations/outlier_hostname.yaml",
    "chars": 472,
    "preview": "id: outlier_hostname\nversion: 1\nmeta:\n  name: Outlier hostname\n  description: >\n    A hostname that appeared in 10% or l"
  },
  {
    "path": "correlations/outlier_ipaddress.yaml",
    "chars": 517,
    "preview": "id: outlier_ipaddress\nversion: 1\nmeta:\n  name: Outlier IP address\n  description: >\n    An IP address that appeared in 10"
  },
  {
    "path": "correlations/outlier_registrar.yaml",
    "chars": 608,
    "preview": "id: outlier_registrar\nversion: 1\nmeta:\n  name: Outlier registrar\n  description: >\n    A registrar that appeared in 10% o"
  },
  {
    "path": "correlations/outlier_webserver.yaml",
    "chars": 617,
    "preview": "id: outlier_webserver\nversion: 1\nmeta:\n  name: Outlier web server\n  description: >\n    A web server that appeared in 10%"
  },
  {
    "path": "correlations/remote_desktop_exposed.yaml",
    "chars": 726,
    "preview": "id: remote_desktop_exposed\nversion: 1\nmeta:\n  name: Remote desktop technology found exposed to the Internet\n  descriptio"
  },
  {
    "path": "correlations/root_path_needs_auth.yaml",
    "chars": 663,
    "preview": "id: root_path_needs_auth\nversion: 1\nmeta:\n  name: Website root path needs authentication\n  description: >\n    The base p"
  },
  {
    "path": "correlations/stale_host.yaml",
    "chars": 1243,
    "preview": "id: stale_host\nversion: 1\nmeta:\n  name: Stale host found\n  description: >\n    A host appears to be stale based upon vari"
  },
  {
    "path": "correlations/strong_affiliate_certs.yaml",
    "chars": 1048,
    "preview": "id: strong_affiliate_certs\nversion: 1\nmeta:\n  name: Affiliated host/domain with strong relationship to the target\n  desc"
  },
  {
    "path": "correlations/strong_similardomain_crossref.yaml",
    "chars": 753,
    "preview": "id: strong_similardomain_crossref\nversion: 1\nmeta:\n  name: Similar domain with strong relationship to the target\n  descr"
  },
  {
    "path": "correlations/template.yaml",
    "chars": 3437,
    "preview": "# Set the ID for the rule. Ensure it matches the filename (without the .yaml\n# extension) and has no spaces or other spe"
  },
  {
    "path": "correlations/vulnerability_critical.yaml",
    "chars": 496,
    "preview": "id: vulnerability_critical\nversion: 1\nmeta:\n  name: At least one CRITICAL-rated vulnerability was found\n  description: >"
  },
  {
    "path": "correlations/vulnerability_high.yaml",
    "chars": 476,
    "preview": "id: vulnerability_high\nversion: 1\nmeta:\n  name: At least one HIGH-rated vulnerability was found\n  description: >\n    A v"
  },
  {
    "path": "correlations/vulnerability_mediumlow.yaml",
    "chars": 721,
    "preview": "id: vulnerability_mediumlow\nversion: 1\nmeta:\n  name: Multiple MEDIUM or LOW-rated vulnerabilities were found\n  descripti"
  },
  {
    "path": "docker-compose-dev.yml",
    "chars": 78,
    "preview": "version: \"3\"\n\nservices:\n  spiderfoot:\n    volumes:\n      - .:/home/spiderfoot\n"
  },
  {
    "path": "docker-compose-full.yml",
    "chars": 103,
    "preview": "version: \"3\"\n\nservices:\n  spiderfoot:\n    build:\n      context: ./\n      dockerfile: ./Dockerfile.full\n"
  },
  {
    "path": "docker-compose.yml",
    "chars": 816,
    "preview": "version: \"3\"\n\n# Basic usage:\n#     $ docker-compose up\n#\n# Dev environment (code directory mapped into container):\n#    "
  },
  {
    "path": "docs/Makefile",
    "chars": 634,
    "preview": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the "
  },
  {
    "path": "docs/conf.py",
    "chars": 2519,
    "preview": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common op"
  },
  {
    "path": "docs/index.rst",
    "chars": 460,
    "preview": ".. spiderfoot documentation master file, created by\n   sphinx-quickstart on Sat Jun 26 01:55:34 2021.\n   You can adapt t"
  },
  {
    "path": "docs/make.bat",
    "chars": 795,
    "preview": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sp"
  },
  {
    "path": "docs/spiderfoot.rst",
    "chars": 864,
    "preview": "spiderfoot package\n==================\n\nSubmodules\n----------\n\nspiderfoot.db module\n--------------------\n\n.. automodule::"
  },
  {
    "path": "generate-certificate",
    "chars": 489,
    "preview": "#!/bin/sh\nif ! command -v openssl >/dev/null 2>&1 ; then\n  echo \"Error: Could not find openssl in \\$PATH: $PATH\"\n  exit "
  },
  {
    "path": "modules/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "modules/sfp__stor_db.py",
    "chars": 1958,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp__stor_stdout.py",
    "chars": 3661,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_abstractapi.py",
    "chars": 11316,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_abusech.py",
    "chars": 14443,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_abuseipdb.py",
    "chars": 10168,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_abusix.py",
    "chars": 11015,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_accounts.py",
    "chars": 14829,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_adblock.py",
    "chars": 6458,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_adguard_dns.py",
    "chars": 4148,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ahmia.py",
    "chars": 5937,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_alienvault.py",
    "chars": 19843,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_alienvaultiprep.py",
    "chars": 7421,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_apple_itunes.py",
    "chars": 5800,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_archiveorg.py",
    "chars": 7853,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_arin.py",
    "chars": 6680,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_azureblobstorage.py",
    "chars": 5833,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_base64.py",
    "chars": 2928,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_bgpview.py",
    "chars": 7469,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_binaryedge.py",
    "chars": 17103,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_bingsearch.py",
    "chars": 4430,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_bingsharedip.py",
    "chars": 6898,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_binstring.py",
    "chars": 4911,
    "preview": "# coding: utf-8\n# -------------------------------------------------------------------------------\n# Name:         sfp_bi"
  },
  {
    "path": "modules/sfp_bitcoin.py",
    "chars": 3045,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_bitcoinabuse.py",
    "chars": 6000,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_bitcoinwhoswho.py",
    "chars": 4324,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_blockchain.py",
    "chars": 3560,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_blocklistde.py",
    "chars": 7574,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_botscout.py",
    "chars": 6261,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_botvrij.py",
    "chars": 5866,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_builtwith.py",
    "chars": 10943,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_builtwith\n# Purpos"
  },
  {
    "path": "modules/sfp_c99.py",
    "chars": 15209,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_callername.py",
    "chars": 4692,
    "preview": "# -------------------------------------------------------------------------------\n# Name:        sfp_callername\n# Purpos"
  },
  {
    "path": "modules/sfp_censys.py",
    "chars": 15507,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_certspotter.py",
    "chars": 9574,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_cinsscore.py",
    "chars": 6231,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_circllu.py",
    "chars": 10119,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_citadel.py",
    "chars": 5557,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_cleanbrowsing.py",
    "chars": 6817,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_cleantalk.py",
    "chars": 7135,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_clearbit.py",
    "chars": 10096,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_clearbit\n# Purpose"
  },
  {
    "path": "modules/sfp_cloudflaredns.py",
    "chars": 4925,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_coinblocker.py",
    "chars": 6445,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_commoncrawl.py",
    "chars": 6623,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_comodo.py",
    "chars": 4484,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_company.py",
    "chars": 6208,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_cookie.py",
    "chars": 2320,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_countryname.py",
    "chars": 8208,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_creditcard.py",
    "chars": 2293,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_crobat_api.py",
    "chars": 5317,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_crossref.py",
    "chars": 5663,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_crt.py",
    "chars": 7988,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_crxcavator.py",
    "chars": 8598,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_customfeed.py",
    "chars": 9834,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_cybercrimetracker.py",
    "chars": 6888,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_debounce.py",
    "chars": 3354,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dehashed.py",
    "chars": 8511,
    "preview": "# -------------------------------------------------------------------------------\n# Name:        sfp_dehashed\n# Purpose:"
  },
  {
    "path": "modules/sfp_digitaloceanspace.py",
    "chars": 6893,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dns_for_family.py",
    "chars": 3467,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnsbrute.py",
    "chars": 8309,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnscommonsrv.py",
    "chars": 4293,
    "preview": "# -*- coding: utf-8 -*-\n# -----------------------------------------------------------------------------\n# Name:         "
  },
  {
    "path": "modules/sfp_dnsdb.py",
    "chars": 12216,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnsdumpster.py",
    "chars": 5141,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnsgrep.py",
    "chars": 5485,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnsneighbor.py",
    "chars": 6871,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnsraw.py",
    "chars": 6365,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnsresolve.py",
    "chars": 21495,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dnszonexfer.py",
    "chars": 4110,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_dronebl.py",
    "chars": 8809,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_duckduckgo.py",
    "chars": 4744,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_email.py",
    "chars": 3353,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_emailcrawlr.py",
    "chars": 7433,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_emailformat.py",
    "chars": 3674,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_emailrep.py",
    "chars": 5166,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_emergingthreats.py",
    "chars": 6607,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_errors.py",
    "chars": 3664,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ethereum.py",
    "chars": 2279,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_etherscan.py",
    "chars": 4555,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_filemeta.py",
    "chars": 7147,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_flickr.py",
    "chars": 9348,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_focsec.py",
    "chars": 6040,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_fortinet.py",
    "chars": 4289,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_fraudguard.py",
    "chars": 10791,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_fsecure_riddler.py",
    "chars": 8913,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_fullcontact.py",
    "chars": 9070,
    "preview": "# -------------------------------------------------------------------------------\n# Name:        sfp_fullcontact\n# Purpo"
  },
  {
    "path": "modules/sfp_fullhunt.py",
    "chars": 7098,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_github.py",
    "chars": 9873,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_gleif.py",
    "chars": 9203,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_google_tag_manager.py",
    "chars": 5776,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_googlemaps.py",
    "chars": 5610,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_googleobjectstorage.py",
    "chars": 6855,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_googlesafebrowsing.py",
    "chars": 7672,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_googlesearch.py",
    "chars": 5058,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_gravatar.py",
    "chars": 7361,
    "preview": "# -------------------------------------------------------------------------------\n# Name:        sfp_gravatar\n# Purpose:"
  },
  {
    "path": "modules/sfp_grayhatwarfare.py",
    "chars": 5885,
    "preview": "# -------------------------------------------------------------------------------\n# Name:        sfp_grayhatwarfare\n# Pu"
  },
  {
    "path": "modules/sfp_greensnow.py",
    "chars": 6443,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_grep_app.py",
    "chars": 7755,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_greynoise.py",
    "chars": 13449,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_greynoise_community.py",
    "chars": 6620,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_h1nobbdde.py",
    "chars": 3543,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_h1.nobbd.de\n# Purp"
  },
  {
    "path": "modules/sfp_hackertarget.py",
    "chars": 12673,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_hashes.py",
    "chars": 2291,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_haveibeenpwned.py",
    "chars": 8390,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_haveibeenpwned\n# P"
  },
  {
    "path": "modules/sfp_honeypot.py",
    "chars": 8613,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_hosting.py",
    "chars": 3283,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_hostio.py",
    "chars": 7712,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_hunter.py",
    "chars": 6025,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_hunter\n# Purpose: "
  },
  {
    "path": "modules/sfp_hybrid_analysis.py",
    "chars": 9358,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_iban.py",
    "chars": 2270,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_iknowwhatyoudownload.py",
    "chars": 5359,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_iknowwhatyoudownlo"
  },
  {
    "path": "modules/sfp_intelx.py",
    "chars": 11440,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_intfiles.py",
    "chars": 2299,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ipapico.py",
    "chars": 3753,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ipapicom.py",
    "chars": 4919,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ipinfo.py",
    "chars": 4412,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ipqualityscore.py",
    "chars": 8945,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ipregistry.py",
    "chars": 5473,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_ipstack.py",
    "chars": 4118,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_isc.py",
    "chars": 5153,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_jsonwhoiscom.py",
    "chars": 9977,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_junkfiles.py",
    "chars": 8026,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_keybase.py",
    "chars": 9296,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_koodous.py",
    "chars": 7211,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_leakix.py",
    "chars": 9736,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_maltiverse.py",
    "chars": 8915,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_malwarepatrol.py",
    "chars": 6525,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_metadefender.py",
    "chars": 7968,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_mnemonic.py",
    "chars": 9996,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_multiproxy.py",
    "chars": 7248,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_myspace.py",
    "chars": 5214,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_myspace\n# Purpose:"
  },
  {
    "path": "modules/sfp_nameapi.py",
    "chars": 4017,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_names.py",
    "chars": 6626,
    "preview": "# coding: utf-8\n# -------------------------------------------------------------------------------\n# Name:         sfp_na"
  },
  {
    "path": "modules/sfp_networksdb.py",
    "chars": 13602,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_neutrinoapi.py",
    "chars": 9940,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_numverify.py",
    "chars": 6083,
    "preview": "# -------------------------------------------------------------------------------\n# Name:        sfp_numverify\n# Purpose"
  },
  {
    "path": "modules/sfp_onioncity.py",
    "chars": 6928,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_onionsearchengine.py",
    "chars": 6758,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_onyphe.py",
    "chars": 15200,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  },
  {
    "path": "modules/sfp_openbugbounty.py",
    "chars": 4433,
    "preview": "# -------------------------------------------------------------------------------\n# Name:         sfp_openbugbounty\n# Pu"
  },
  {
    "path": "modules/sfp_opencorporates.py",
    "chars": 8534,
    "preview": "# -*- coding: utf-8 -*-\n# -------------------------------------------------------------------------------\n# Name:       "
  }
]

// ... and 595 more files (download for full content)

About this extraction

This page contains the full source code of the smicallef/spiderfoot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 795 files (13.2 MB), approximately 3.5M tokens, and a symbol index with 4203 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!