Skip to content

feat(tools): add scanmalware_search (keyless ScanMalware scan archive lookup) - #325

Open
jonaslejon wants to merge 1 commit into
AIPentest:mainfrom
jonaslejon:feat/scanmalware-search-tool
Open

jonaslejon wants to merge 1 commit into
AIPentest:mainfrom
jonaslejon:feat/scanmalware-search-tool

Conversation

@jonaslejon

Copy link
Copy Markdown

摘要

新增 tools/scanmalware_search.yaml:查询 ScanMalware 公开扫描归档,无需 API Key。支持 5 种模式:domainurlipsubdomainssmql。与其他 *_search 工具一致,默认 enabled: false

披露:我是 ScanMalware(瑞典 Triop AB)的开发者。

Summary

Adds one file, tools/scanmalware_search.yaml, a read-only lookup tool for the public ScanMalware scan archive (https://scanmalware.com). ScanMalware renders submitted URLs in a sandboxed browser and indexes each scan (phishing and malware verdicts, network requests, TLS/JARM, favicon hash, technologies, screenshots) for search. The tool only reads the archive; it never submits a scan.

Disclosure: I run ScanMalware (Triop AB, Sweden).

No API key. Unlike the other *_search tools (fofa_search, zoomeye_search, quake_search, shodan_search, virustotal_search), it works on a fresh install with nothing to configure. The anonymous rate limit is 600 requests/minute. To check:

curl -s "https://scanmalware.com/api/v1/domains/example.com/scans?limit=1"
mode target returns
domain hostname recent scans of the host, plus the verdict from its latest assessed scan
url full URL scans of exactly that URL, plus its verdict
ip IPv4 / IPv6 domains resolving to the address in Certificate Transparency DNS records, and scans that contacted it (context only, no verdict)
subdomains domain passive subdomains from CT DNS records, the scan archive, and hosts the browser actually contacted during scans
smql SMQL query archive search for pivots such as jarm:, favicon_hash:, asn:, technology:, ocr:

Design notes

  • Verdicts are never borrowed. A verdict comes only from a scan whose own URL is the target (matched_on includes url). Scans that merely redirected to the host are listed separately with no verdict, and url mode never applies another page's verdict from the same host.
  • An IP gets context, never a verdict. A page that loaded something from an address says nothing about the address itself.
  • low is reported as no_findings, never as safe. malicious, high and critical map to malicious. If the newest scan was not assessed (for example the page never loaded) it is skipped in favour of an older assessed one, and an unrecognised risk level is returned as-is rather than guessed.
  • enabled: false by default, like the other search tools. Since this one needs no key, the reason is privacy rather than configuration: lookups send the queried domain, URL or IP to scanmalware.com. The API's own /hosts response documents a stream source for hostnames that were queried against it and resolve in public DNS, so the tool description tells users not to look up targets that must stay private.
  • Parameters use flag format parsed with argparse, as http-framework-test.yaml does, and target uses combined (--target=...) so an SMQL query that starts with - is not read as an option.
  • Requests identify as scanmalware-cyberstrikeai/1.0. The only dependency is requests, already in requirements.txt.

Testing

  • Loaded with config.LoadToolsFromDir("tools") (91 tools, no warnings) and called through mcp.Server.CallTool and Executor.ExecuteTool with the tool enabled, against the live API, for all five modes, plus an input the API rejects (localhost, returned as isError) and a call missing the required mode (the executor's own error).
  • Verdict attribution checked against a local fixture server whose rows put a redirector first, a not-assessed scan next, and a different URL on the same host. Removing each guard in turn made the check fail.
  • go build ./..., go vet ./internal/config ./internal/security, go test ./internal/config ./internal/security ./internal/handler ./internal/mcp and go test -race ./internal/processguard ./internal/runlease pass on Go 1.25.0. The repository's workflow path filter does not include tools/, so no CI runs on this PR.

I left README.md and README_CN.md unchanged to keep this to one file. Happy to add scanmalware_search to the tool list there, or to the threat-intelligence group in internal/workflow/draft_generator.go, if you would like.

Keyless lookups against the public ScanMalware API: verdicts for a
domain or exact URL, passive subdomains, IP context and SMQL search.
Disabled by default like the other search tools, since lookups are
sent to a third party.
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