Skip to content

feat: Shodan host-lookup task (passive recon via the Shodan SDK)#1233

Open
ocervell wants to merge 10 commits into
mainfrom
feat/shodan-integration
Open

feat: Shodan host-lookup task (passive recon via the Shodan SDK)#1233
ocervell wants to merge 10 commits into
mainfrom
feat/shodan-integration

Conversation

@ocervell

@ocervell ocervell commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Adds a shodan PythonRunner task: a passive Shodan host lookup (api.host(ip) via the Shodan Python SDK) that maps the response to native, low-confidence secator findings.

What it does

Given a target IP or hostname (hostnames resolved via socket.gethostbyname), it emits:

  • Ip (with org/ISP/ASN/OS/country in extra_data)
  • Subdomain per hostname/domain (deduped)
  • Port per service banner (protocol, product, version, CPEs, excerpted banner) — confidence='low'
  • Technology per product/version/CPE
  • Vulnerability per CVE (top-level + per-banner, with CVSS when present) — confidence='low'
  • Tag for org/ISP/ASN/OS metadata

Findings are low-confidence because Shodan data is from its last crawl, not actively verified (same convention as fuzzing tasks).

Scope (v1)

Host lookup only — no search/count/scan, no CIDR input (documented non-goals). The client init + mapping are factored so search could be added later without a mode-dispatch rewrite.

Config / deps

  • New ShodanAddon (CONFIG.addons.shodan.api_key, mirrors VulnersAddon); key resolution is opt → config → SHODAN_API_KEY env. The api_key opt defaults to '' (never a CONFIG default — that would leak the key into the secator-api UI form).
  • New shodan < 2 extras group (pip install secator[shodan]).

Error handling

Missing key / import error → Error (return); No information availableWarning + zero findings; other APIErrorError; DNS failure → Error for that input; all per-input errors continue with the remaining inputs.

Tests

  • Unit: anonymized fixture + get_mock_context (mocks the SDK + DNS, no network); mapping assertions + low-confidence checks + error-branch tests.
  • Integration: inputs.py/outputs.py entries (live run needs SHODAN_API_KEY).
  • Full unit suite 937 passing, secator test lint clean, secator x shodan <ip> CLI render verified.

Known minor (accepted)

_registered_domain is naive last-two-labels (no Public Suffix List) — acceptable for low-confidence passive OSINT; not worth a PSL dependency.

Design + plan: gke-admin/docs/superpowers/specs/2026-06-29-shodan-integration-design.md and the matching plan.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Shodan support for passive recon, including host lookups, DNS records, and search results.
    • Enabled optional configuration for a Shodan API key and support for installing the related extra.
  • Bug Fixes

    • Improved result mapping so hosts, ports, technologies, subdomains, records, and vulnerabilities are surfaced more consistently.
    • Added clearer handling for missing API keys and Shodan API errors.
  • Documentation

    • Updated the default domain recon workflow to include passive DNS via Shodan when passive mode is enabled.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new Shodan integration to secator: a ShodanAddon config model, an optional shodan dependency extra, and a new shodan task class supporting host, DNS, and search operations with output mapping to secator types. It includes a workflow wiring, CI updates, fixtures, and tests.

Changes

Shodan Task Integration

Layer / File(s) Summary
Config model and optional dependency
pyproject.toml, secator/config.py, .github/actions/install/action.yml
Adds shodan < 2 as an optional extra, defines ShodanAddon (enabled, api_key) registered in Addons, and installs the extra in CI pipx install.
Shodan task class, yielder, host/DNS/search runners
secator/tasks/shodan.py
Implements the shodan task with input/output types, options, yielder() resolving API key and dispatching host/dns/search operations, _run_host/_run_dns/_run_search, mappers _map_host/_map_dns/_map_banner, helper utilities, mock context, and custom validate_input.
Workflow wiring
secator/configs/workflows/domain_recon.yaml
Adds a shodan DNS task gated on opts.passive to the domain recon workflow.
Fixtures and unit/integration tests
tests/fixtures/shodan_output.json, tests/fixtures/shodan_dns_output.json, tests/fixtures/shodan_search_output.json, tests/unit/test_shodan.py, secator/utils_test.py, tests/integration/test_tasks.py
Adds host/DNS/search fixtures, unit tests covering config defaults, output mapping, and error paths, test input/runner options, and integration test skip for shodan.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant yielder
  participant ShodanSDK
  participant Mapper
  Caller->>yielder: iterate(target, operation)
  yielder->>yielder: resolve api_key (opt → CONFIG → env)
  alt operation = host
    yielder->>ShodanSDK: api.host(ip, history, minify)
    ShodanSDK-->>yielder: host dict or APIError
    yielder->>Mapper: _map_host(h)
  else operation = dns
    yielder->>ShodanSDK: api.dns.domain_info()
    ShodanSDK-->>yielder: dns info or APIError
    yielder->>Mapper: _map_dns(domain, info)
  else operation = search
    yielder->>ShodanSDK: api.search(query, limit)
    ShodanSDK-->>yielder: matches
    yielder->>Mapper: _map_banner(b)
  end
  Mapper-->>Caller: Ip, Subdomain, Port, Technology, Vulnerability, Tag, Record
Loading

Possibly related PRs

  • freelabz/secator#743: Extends the same domain_recon.yaml workflow that this PR adds a new shodan task to.
  • freelabz/secator#755: Overlaps in secator/utils_test.py updates to INPUTS_TASKS/runner opts used for task testing.
  • freelabz/secator#967: Introduces the Technology output type that the new Shodan task's mapping depends on.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clearly related to the PR and captures the main addition of a Shodan-based passive recon task, even though the implementation also adds dns and search modes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/shodan-integration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
secator/tasks/shodan.py (1)

139-142: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Use a public-suffix-aware parser for domain.

The last-two-labels heuristic turns values like foo.co.uk into co.uk, so Subdomain.domain becomes wrong for common multi-label suffixes. Please switch this helper to an existing PSL-aware parser/helper before downstream grouping depends on it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@secator/tasks/shodan.py` around lines 139 - 142, The _registered_domain
helper in ShodanTask uses a naive last-two-labels split, which misclassifies
domains with multi-label public suffixes. Update this static method to use an
existing public-suffix-aware parser/helper already available in the codebase so
it returns the correct registrable domain for cases like foo.co.uk, and keep
downstream grouping logic pointed at this corrected domain value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@secator/tasks/shodan.py`:
- Around line 16-29: The shodan task is using PythonRunner instead of the repo’s
Command task contract, so it should be rewritten to match other entries under
secator/tasks/. Update the shodan class to subclass Command and define the
expected cmd, input_type, output_types, install_cmd, and item_loaders surface
instead of the current PythonRunner-specific setup. Keep the existing task
metadata and options, but move any parsing logic into item_loaders so the task
integrates consistently with the framework.
- Line 22: The install hint in shodan task is too loose and can fetch
unsupported versions. Update the install command in shodan.py (the install_cmd
used by the Shodan task) so it matches the version constraint already declared
in pyproject.toml, pinning shodan to the supported <2 range. Keep the change
localized to the task’s install hint string so the built-in install path stays
aligned with the dependency policy.
- Around line 93-95: The Shodan host vulnerability branch in shodan.py currently
yields only the CVE ID from h.get('vulns'), dropping attached metadata. Update
the vuln handling in the same area as the host parsing logic that builds
Vulnerability objects so it mirrors the banner-path normalization, extracting
any Shodan metadata from each vuln entry and populating cvss_score and summary
on the yielded finding instead of discarding them.

In `@tests/unit/test_shodan.py`:
- Around line 21-25: The _run helper in test_shodan.py imports output_types
symbols it never uses, which triggers Flake8 F401. Remove the unused
secator.output_types import from _run and keep only the symbols actually
referenced by the test helper, leaving shodan._map_host and _load_fixture
unchanged.

---

Nitpick comments:
In `@secator/tasks/shodan.py`:
- Around line 139-142: The _registered_domain helper in ShodanTask uses a naive
last-two-labels split, which misclassifies domains with multi-label public
suffixes. Update this static method to use an existing public-suffix-aware
parser/helper already available in the codebase so it returns the correct
registrable domain for cases like foo.co.uk, and keep downstream grouping logic
pointed at this corrected domain value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7ddaa95f-965e-4a1c-b390-a591d93a77b5

📥 Commits

Reviewing files that changed from the base of the PR and between e26f394 and 13d489b.

📒 Files selected for processing (8)
  • pyproject.toml
  • secator/config.py
  • secator/tasks/shodan.py
  • secator/utils_test.py
  • tests/fixtures/shodan_output.json
  • tests/integration/inputs.py
  • tests/integration/outputs.py
  • tests/unit/test_shodan.py

Comment thread secator/tasks/shodan.py
Comment on lines +16 to +29
@task()
class shodan(PythonRunner):
"""Passive host recon via the Shodan API (ports, services, CVEs, hostnames)."""
input_types = [HOST, IP]
output_types = [Ip, Subdomain, Port, Technology, Vulnerability, Tag]
tags = ['shodan', 'recon', 'osint', 'passive']
install_cmd = 'pip install shodan'
opts = {
# Empty default + runtime fallback (never a CONFIG default — it would leak
# the configured key into the secator-api UI form, like the `ai` task).
'api_key': {'type': str, 'default': '', 'help': 'Shodan API key (defaults to configured key)'},
'history': {'is_flag': True, 'default': False, 'help': 'Include historical (non-current) banners'},
'minify': {'is_flag': True, 'default': False, 'help': 'Only ports + general host info (no banners)'},
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Use the repo’s Command task contract here.

This new tool is wired up as a PythonRunner, so it never defines the Command-style cmd/input_type/item_loaders surface the repo expects for new entries under secator/tasks/. Please align the implementation with that contract before more tasks copy this pattern.

As per coding guidelines, secator/tasks/*.py should “Use Command subclass in secator/tasks/ to integrate new tools, defining cmd, input_type, output_types, and install_cmd attributes” and “Implement custom output parsers via item_loaders in task Command subclasses”.

🧰 Tools
🪛 Ruff (0.15.20)

[warning] 19-19: Mutable default value for class attribute

(RUF012)


[warning] 20-20: Mutable default value for class attribute

(RUF012)


[warning] 21-21: Mutable default value for class attribute

(RUF012)


[warning] 23-29: Mutable default value for class attribute

(RUF012)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@secator/tasks/shodan.py` around lines 16 - 29, The shodan task is using
PythonRunner instead of the repo’s Command task contract, so it should be
rewritten to match other entries under secator/tasks/. Update the shodan class
to subclass Command and define the expected cmd, input_type, output_types,
install_cmd, and item_loaders surface instead of the current
PythonRunner-specific setup. Keep the existing task metadata and options, but
move any parsing logic into item_loaders so the task integrates consistently
with the framework.

Source: Coding guidelines

Comment thread secator/tasks/shodan.py
input_types = [HOST, IP]
output_types = [Ip, Subdomain, Port, Technology, Vulnerability, Tag]
tags = ['shodan', 'recon', 'osint', 'passive']
install_cmd = 'pip install shodan'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repo root: '; pwd
printf '\nFiles matching shodan task / dependency hints:\n'
git ls-files | rg '(^|/)(shodan|requirements|pyproject|setup|Pipfile|poetry|flake8|tasks/.*\.py)$'

printf '\n--- secator/tasks/shodan.py ---\n'
if [ -f secator/tasks/shodan.py ]; then
  cat -n secator/tasks/shodan.py
fi

printf '\n--- dependency references to shodan ---\n'
rg -n --hidden --no-ignore-vcs '\bshodan\b|shodan < 2|shodan<2|pip install shodan' . \
  -g '!**/.git/**' -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**' -g '!**/venv/**' -g '!**/.venv/**'

Repository: freelabz/secator

Length of output: 11136


Pin the Shodan install hint to match the dependency. pyproject.toml already constrains shodan to <2, but secator/tasks/shodan.py:22 still advertises pip install shodan, so the built-in install path can pull an unsupported release.

Proposed fix
-	install_cmd = 'pip install shodan'
+	install_cmd = 'pip install "shodan<2"'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
install_cmd = 'pip install shodan'
install_cmd = 'pip install "shodan<2"'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@secator/tasks/shodan.py` at line 22, The install hint in shodan task is too
loose and can fetch unsupported versions. Update the install command in
shodan.py (the install_cmd used by the Shodan task) so it matches the version
constraint already declared in pyproject.toml, pinning shodan to the supported
<2 range. Keep the change localized to the task’s install hint string so the
built-in install path stays aligned with the dependency policy.

Comment thread secator/tasks/shodan.py
Comment on lines +93 to +95
for cve in (h.get('vulns') or []):
yield Vulnerability(name=cve, id=cve, matched_at=ip_str, ip=ip_str,
provider='shodan', confidence='low', tags=['shodan'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve Shodan host vuln metadata
h['vulns'] can include Shodan metadata, but this branch emits only the CVE ID. Mirror the banner-path normalization here so top-level findings keep cvss_score and summary instead of dropping them.

🧰 Tools
🪛 Flake8 (7.3.0)

[error] 95-95: continuation line under-indented for visual indent

(E128)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@secator/tasks/shodan.py` around lines 93 - 95, The Shodan host vulnerability
branch in shodan.py currently yields only the CVE ID from h.get('vulns'),
dropping attached metadata. Update the vuln handling in the same area as the
host parsing logic that builds Vulnerability objects so it mirrors the
banner-path normalization, extracting any Shodan metadata from each vuln entry
and populating cvss_score and summary on the yielded finding instead of
discarding them.

Comment thread tests/unit/test_shodan.py
Comment on lines +21 to +25
def _run(self):
from secator.output_types import Ip, Subdomain, Port, Technology, Vulnerability, Tag
from secator.tasks.shodan import shodan
task = shodan.__new__(shodan)
return list(task._map_host(_load_fixture(), '10.0.0.1', 'host1.example.com'))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Drop the unused output_types import from _run().

Line 22 is unused and already trips Flake8 F401, so this helper won’t stay lint-clean as written.

As per coding guidelines, **/*.py should use Flake8 with the repo’s configured settings.

🧰 Tools
🪛 Flake8 (7.3.0)

[error] 22-22: 'secator.output_types.Ip' imported but unused

(F401)


[error] 22-22: 'secator.output_types.Subdomain' imported but unused

(F401)


[error] 22-22: 'secator.output_types.Port' imported but unused

(F401)


[error] 22-22: 'secator.output_types.Technology' imported but unused

(F401)


[error] 22-22: 'secator.output_types.Vulnerability' imported but unused

(F401)


[error] 22-22: 'secator.output_types.Tag' imported but unused

(F401)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_shodan.py` around lines 21 - 25, The _run helper in
test_shodan.py imports output_types symbols it never uses, which triggers Flake8
F401. Remove the unused secator.output_types import from _run and keep only the
symbols actually referenced by the test helper, leaving shodan._map_host and
_load_fixture unchanged.

Sources: Coding guidelines, Linters/SAST tools

ocervell added 4 commits June 30, 2026 07:05
Add shodan step (operation: dns, if: opts.passive) to domain_recon
tasks._group so passive recon runs include Shodan DNS records alongside dnsx.

Also fix two dispatch bugs found during smoke testing:
- Add STRING to input_types so free-text search queries are not filtered
  out by the framework's type guard before reaching the task.
- Move operation validation before the API-key check so unknown operations
  yield a clean 'Unknown Shodan operation' Error regardless of key config.
@ocervell

Copy link
Copy Markdown
Contributor Author

Update: multi-mode expansion (host + DNS + search)

This PR now extends the host-lookup task into a single multi-mode shodan task via an operation opt (host default | dns | search):

  • -op dnsapi.dns.domain_infoRecord (per record_types: A/AAAA/CNAME/MX/NS/TXT/SOA) + Ip (public A/AAAA only) + Subdomain. Passive, dnsx-style. One call/domain.
  • -op searchapi.search(query, limit=100) → a total Tag + per-match Ip/Subdomain/Port/Technology/Vulnerability (reuses the host banner mapper). Query is the task input.
  • host --resolver shodan — resolve hostnames via Shodan DNS instead of the local resolver ("support both").
  • domain_recon — added a passive Shodan-DNS step (operation: dns, if: opts.passive) alongside dnsx.

Refactor extracted a shared _map_banner (host + search). Only Record was added to output types. Port/Vulnerability stay confidence='low'.

Verification: full unit suite 945 passed, secator test lint clean, CLI smoke for all three modes + the unknown-operation guard render cleanly. Final review verdict: READY.

Known minors (for your call — non-blocking)

  1. Workflow noise: domain_recon --passive with no Shodan key configured emits one "key not configured" Error per run (the step fires on opts.passive). Doesn't fail the workflow. Cleanly gating on "addon enabled" isn't supported by the workflow if: engine (opts-only scope) — left as an informative signal; reconsider if you'd rather gate it differently.
  2. STRING in input_types (needed so a free-text search query passes the framework type-guard) also lets shodan be auto-fed upstream STRING outputs in busier workflows — low risk, noted.
  3. _map_banner assumes banner['vulns'] is a dict (pre-existing, moved verbatim from host; matches Shodan's shape).
  4. _map_dns emits two Ip for apex+www sharing one address (different host) — intentional, deduped downstream.

🤖 Generated with Claude Code

ocervell and others added 2 commits June 30, 2026 18:36
CI installs `.[dev,ai]` only, so the `shodan` SDK wasn't present in secator's
pipx venv — the unit tests that import shodan (error-path + search) and the
shodan integration task failed with "No module named 'shodan'". Add `shodan`
to the install extras (mirrors how `ai`/litellm is included) so the task and
its tests run in CI.

Also remove the shodan entry from the integration inputs/outputs: a live
`api.host()` integration run needs a real SHODAN_API_KEY (network), which CI
has no secret for, so it can only ever FAILURE. The mocked unit tests are the
offline coverage; a live integration test can be added later behind a key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5vSjfkBuGAAHdKxHS3ySm
…API_KEY)

The test_tasks loop auto-discovers every registered task and falls back to
the generic HOST input when a task has no INPUTS_TASKS entry, so simply
dropping the shodan input still ran shodan on 'localhost' and failed without
a live SHODAN_API_KEY. Skip it explicitly like msfconsole.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5vSjfkBuGAAHdKxHS3ySm

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
secator/tasks/shodan.py (1)

255-258: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Naive TLD parsing breaks on multi-label public suffixes.

_registered_domain takes the last two labels, which is wrong for suffixes like co.uk, com.au, etc. (e.g. foo.example.co.ukco.uk). This feeds Subdomain.domain in _map_host/_run_search/_run_dns and the suffix-stripping logic in _shodan_resolve (Line 140), so results can be grouped/resolved incorrectly for such domains.

Please confirm whether the project already depends on (or is open to adding) a public-suffix-aware library such as tldextract for this; if a lightweight in-house heuristic is intentional for v1, consider documenting the limitation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@secator/tasks/shodan.py` around lines 255 - 258, The _registered_domain
helper in ShodanTask is using a naive last-two-label split, which breaks domain
grouping and resolution for multi-label public suffixes like co.uk or com.au.
Update _registered_domain (and any callers such as _map_host, _run_search,
_run_dns, and the suffix stripping in _shodan_resolve) to use a
public-suffix-aware approach, preferably via tldextract if the project can
depend on it. If adding a dependency is not desired for v1, keep the current
heuristic but document its limitation clearly where _registered_domain is
defined.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@secator/tasks/shodan.py`:
- Around line 255-258: The _registered_domain helper in ShodanTask is using a
naive last-two-label split, which breaks domain grouping and resolution for
multi-label public suffixes like co.uk or com.au. Update _registered_domain (and
any callers such as _map_host, _run_search, _run_dns, and the suffix stripping
in _shodan_resolve) to use a public-suffix-aware approach, preferably via
tldextract if the project can depend on it. If adding a dependency is not
desired for v1, keep the current heuristic but document its limitation clearly
where _registered_domain is defined.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4fc0ba3-f9b8-4b92-aabf-cd410f322bf1

📥 Commits

Reviewing files that changed from the base of the PR and between 13d489b and aa09878.

📒 Files selected for processing (7)
  • .github/actions/install/action.yml
  • secator/configs/workflows/domain_recon.yaml
  • secator/tasks/shodan.py
  • tests/fixtures/shodan_dns_output.json
  • tests/fixtures/shodan_search_output.json
  • tests/integration/test_tasks.py
  • tests/unit/test_shodan.py
✅ Files skipped from review due to trivial changes (1)
  • tests/fixtures/shodan_search_output.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant