{"id":48714835,"url":"https://github.com/blisspixel/recon","last_synced_at":"2026-06-10T05:01:01.323Z","repository":{"id":350581505,"uuid":"1207478328","full_name":"blisspixel/recon","owner":"blisspixel","description":"Passive recon tool. Zero credentials required. Finds Microsoft 365 \u0026 Google Workspace tenants, scores email security, fingerprints 800+ SaaS/infrastructure services via DNS \u0026 certificates, and ships a native MCP server for AI agents","archived":false,"fork":false,"pushed_at":"2026-06-06T04:04:18.000Z","size":6135,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T05:24:13.656Z","etag":null,"topics":["domain-intelligence","email-security","m365","mcp","microsoft365","osint","passive-recon","recon","reconnaissance"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blisspixel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-11T01:49:37.000Z","updated_at":"2026-06-06T03:51:57.000Z","dependencies_parsed_at":"2026-04-17T17:00:55.017Z","dependency_job_id":null,"html_url":"https://github.com/blisspixel/recon","commit_stats":null,"previous_names":["blisspixel/recon"],"tags_count":150,"template":false,"template_full_name":null,"purl":"pkg:github/blisspixel/recon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blisspixel%2Frecon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blisspixel%2Frecon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blisspixel%2Frecon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blisspixel%2Frecon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blisspixel","download_url":"https://codeload.github.com/blisspixel/recon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blisspixel%2Frecon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34137570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["domain-intelligence","email-security","m365","mcp","microsoft365","osint","passive-recon","recon","reconnaissance"],"created_at":"2026-04-11T16:14:45.405Z","updated_at":"2026-06-10T05:01:01.306Z","avatar_url":"https://github.com/blisspixel.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# recon\n\n[![CI](https://github.com/blisspixel/recon/actions/workflows/ci.yml/badge.svg)](https://github.com/blisspixel/recon/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/recon-tool.svg?cacheSeconds=300)](https://pypi.org/project/recon-tool/)\n[![Python](https://img.shields.io/pypi/pyversions/recon-tool.svg?cacheSeconds=300)](https://pypi.org/project/recon-tool/)\n[![License](https://img.shields.io/pypi/l/recon-tool.svg?cacheSeconds=300)](LICENSE)\n\nPassive domain intelligence from public sources. Queries DNS records, Microsoft/Google identity endpoints, and certificate transparency logs to build a picture of an organization's technology stack: no credentials, no API keys, no active scanning.\n\nDrop in a domain, get an evidence-backed read on its identity stack, email posture, and cloud footprint in seconds, with the uncertainty widened when the public channel is sparse.\n\n\u003e **Defensive use only.** recon is designed for legitimate security posture assessment, IT architecture review, vendor due diligence, and defensive hardening. It performs zero active scanning and zero credentialed access. See [docs/legal.md](docs/legal.md) for the full intended-use policy.\n\n```bash\nrecon contoso.com\n```\n\n```\nContoso Ltd\ncontoso.com\n──────────────────────────────────────────────────────────────────────────────\n  Provider     Microsoft 365 (primary) via Proofpoint gateway + Google Workspace (secondary)\n  Tenant       a1b2c3d4-e5f6-7890-abcd-ef1234567890 • NA\n  Auth         Federated (Entra ID + Google Workspace)\n  Confidence   ●●● High (4 sources)\n\nServices\n  Email          Microsoft 365, Google Workspace, Proofpoint, DMARC, DKIM,\n                 SPF: strict (-all), BIMI\n  Identity       Okta, Google Workspace (managed identity)\n  Cloud          Cloudflare (CDN), AWS Route 53 (DNS)\n  Security       Wiz, CAA: 3 issuers restricted\n  Collaboration  Slack, Atlassian (Jira/Confluence)\n\nHigh-signal related domains\n  api.contoso.com, login.contoso.com, portal.contoso.com, sso.contoso.com,\n  admin.contoso.com, status.contoso.com, support.contoso.com\n  (57 total, 50 more, use --full to see all)\n\nInsights\n  Federated identity indicators observed (likely Okta, enterprise SSO)\n  Email security 4/5: DMARC reject, DKIM, SPF strict, BIMI\n  Email gateway: Proofpoint in front of Exchange\n  Dual provider: Google + Microsoft coexistence\n```\n\n\u003e Examples use [Microsoft's fictional company names](https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges) (Contoso, Northwind Traders, Fabrikam). Tenant IDs, services, and domains are fabricated. No real company is depicted.\n\nWorks for Microsoft 365, Google Workspace, or any provider. Also runs as an [MCP server](docs/mcp.md) for AI agents; the default `pip install recon-tool` includes MCP support.\n\n**Jump to:** [Install](#install) · [Usage](#usage) · [How it works](#how-recon-works) · [AI agents and MCP](#mcp-server) · [Automation and JSON](#automation-and-json) · [Limitations](#limitations) · [Docs index](docs/README.md)\n\n## Why recon?\n\n| If you need... | Use recon for... | Reach for something heavier when... |\n|---|---|---|\n| Fast external stack context | Passive DNS, identity-endpoint, CT, SaaS, and posture indicators with no credentials | You need authenticated tenant inventory or asset-management truth |\n| Defensive review or vendor diligence | Hedged observations and evidence traces you can verify | You need vulnerability scanning, exploit checks, or host-level facts |\n| Automation-friendly output | Stable `--json`, batch mode, delta mode, and local MCP tools | You need dashboards, scheduled monitoring, or report generation |\n\n## recon in practice\n\nrecon is a zero-credential first pass for external technology-stack and posture visibility. Run it before a vendor diligence call, a partner integration, an M\u0026A review, or a hardening audit. Output is hedged, traceable, and shaped for downstream automation.\n\nrecon does not replace commercial EASM platforms, active scanners, or continuous monitoring. It is the upstream signal that feeds those tools, with full provenance so you can verify any conclusion before you act on it.\n\nrecon also does not score or rank organizations, enrich domains with firmographics, or maintain an industry intelligence database. It reports what the public channel reveals, with provenance, and leaves business interpretation to the operator.\n\nrecon ships as a Python wheel on PyPI and runs locally: a CLI, an importable library, and a stdio MCP server. It is not a hosted service. There is no remote MCP transport, container image, daemon, or scheduled-monitoring mode, and adding one is out of scope by design (see the [roadmap](docs/roadmap.md#intentionally-out-of-scope)). If you need scheduling or shared access, that belongs to whatever runs recon, not to recon itself.\n\n## How recon works\n\nrecon reads the public channel: DNS records (MX, CNAME, SPF, DMARC,\nTXT), certificate-transparency SAN sets, and the unauthenticated\nidentity-discovery endpoints Microsoft and Google publish for tenant\nresolution. No credentials, no port scanning, no login attempts. By\ndefault the only request the queried domain's own servers see is the\nstandard MTA-STS policy fetch; two direct-probe enrichments (the Google\nCSE discovery endpoint at `cse.\u003cdomain\u003e` and the BIMI VMC certificate\nfetch) are opt-in behind `--direct-probes` and stay off unless you ask\nfor them. BIMI presence is still read from DNS either way.\n\nIt then runs those observables through a small Bayesian network and\nreports each high-level claim (M365 tenant, federated identity,\nemail-policy enforcement, CDN fronting, and so on) as an 80% confidence\ninterval, not a yes/no verdict. The interval is the load-bearing field:\non hardened or heavily-proxied targets it **widens** rather than\ncollapsing on a fake-confident point estimate, because absent evidence\nis treated as no evidence, not as evidence of absence. The intervals\nare evidence-responsive (they track how much the public channel\nconstrains each claim); they are not yet empirically calibrated against\nground truth, which no passive tool can observe. The structural motifs\nrecon surfaces (a CDN in front of an identity provider, an email\ngateway in front of M365, a secondary Google Workspace alongside\nprimary M365) are the ones single-source detection often misses.\n\n\u003e **For the formal model:** the adversarial missing-data treatment\n\u003e (MNAR, with the absent-evidence rule grounded in m-graphs and Manski\n\u003e partial identification), the calibration principles the credible\n\u003e interval satisfies, and the failure-mode catalog across five hardening\n\u003e postures live in [docs/correlation.md](docs/correlation.md).\n\nThe fingerprint catalog is shaped by passive-DNS observation of real\ncorpora. The built-in catalog ships with the package; operators can\nextend it for their own environment by dropping additions into\n`~/.recon/fingerprints.yaml` (additive only, cannot override\nbuilt-ins). Anything broadly useful can be contributed upstream via\nthe workflow in [CONTRIBUTING.md](CONTRIBUTING.md). The maintainer\nruns the same scan-triage loop against a private corpus before each\nrelease; the catalog grows from observed gaps, not invented entries.\n\n## Install\n\nRequires Python 3.11+.\n\n```bash\npip install recon-tool                 # includes MCP server\npip install -U recon-tool              # upgrade\nrecon doctor                           # verify connectivity\n```\n\n## Usage\n\n```bash\nrecon contoso.com                              # default panel\nrecon contoso.com --explain                    # full reasoning + provenance DAG\nrecon contoso.com --full                       # everything (services + domains + posture)\nrecon contoso.com --profile fintech            # apply a posture lens\nrecon contoso.com --confidence-mode strict     # drop hedging on dense-evidence targets (current)\nrecon contoso.com --direct-probes              # opt in to direct CSE / BIMI-VMC probes (off by default)\nrecon contoso.com --json                       # structured JSON for piping\nrecon batch domains.txt --json                 # batch (cross-domain token clustering)\ncat domains.txt | recon batch - --json         # batch reading domains from stdin\nrecon batch domains.txt --json --include-ecosystem  # add v1.8 ecosystem hypergraph\nrecon batch domains.txt --summary              # one aggregate-only cohort summary (panel)\nrecon batch domains.txt --summary --json       # the same, as JSON for downstream tooling\nrecon contoso.com --chain --depth 2            # follow related-domain breadcrumbs\nrecon delta contoso.com                        # diff against last cached snapshot\nrecon mcp                                      # start MCP server (stdio)\n```\n\nBuilt-in profiles: `fintech`, `healthcare`, `saas-b2b`, `high-value-target`, `public-sector`, `higher-ed`. Custom profiles live in `~/.recon/profiles/*.yaml`.\n\n**Shell completion.** recon ships tab-completion for the command tree and flags (via Typer). Install it for your current shell, or print the script to wire it up yourself:\n\n```bash\nrecon --install-completion                     # add completion to your shell config\nrecon --show-completion                        # print the completion script (bash/zsh/fish/powershell)\n```\n\nAfter `--install-completion`, start a new shell for it to take effect.\n\nSee [docs/README.md](docs/README.md) for the organized documentation index.\n\n## MCP server\n\nrecon runs as an MCP server for Claude, Cursor, VS Code, ChatGPT, or any MCP client. The Model Context Protocol lets AI agents call tools like recon directly from your chat.\n\n**One-shot install.** Let recon write the right config block for you:\n\n```bash\nrecon mcp install --client=claude-desktop   # or claude-code, cursor, vscode, windsurf, kiro\nrecon mcp doctor                            # spawn the server and verify the JSON-RPC handshake\n```\n\nThe install command is idempotent and merge-safe: sibling MCP servers, hand-curated `autoApprove` lists, custom `env` vars, and any other keys you've added to the recon block all survive a `--force` rerun. Use `--dry-run` first to preview the plan.\n\n**Manual install.** If you'd rather edit by hand, add this to your client's MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"recon\": {\n      \"command\": \"recon\",\n      \"args\": [\"mcp\"],\n      \"autoApprove\": []\n    }\n  }\n}\n```\n\nThe default install already includes the MCP server. Keep approvals manual until you've decided which tools, if any, you want to trust automatically. recon's MCP tools are split into read-only and stateful sets (the three ephemeral-fingerprint / reload tools are stateful); see the [autoApprove guidance](docs/mcp.md#read-only-vs-stateful-autoapprove-guidance) for which is which.\n\nThen ask your AI: *\"Run a recon lookup on contoso.com and tell me what's running.\"*\n\nSee [docs/mcp.md](docs/mcp.md) for the full tool list, advanced agentic workflows, and per-client config locations.\n\nInstalled but the tools don't appear? Run `recon doctor --client=\u003cname\u003e` to confirm the config carries the recon stanza, then see the [troubleshooting checklist](docs/mcp.md#when-doctor-passes-but-the-tools-dont-load). The usual fix is a full application restart, since a new chat does not re-spawn MCP servers.\n\n**Claude Code, Kiro, Windsurf, Cursor, VS Code:** per-agent install scaffolds live under [`agents/`](agents/), one folder per client with its MCP config and guidance template. Claude Code users get a full plugin (MCP + skill in one install) at [`agents/claude-code/`](agents/claude-code/). The skill drives the CLI for the one-shot analyses (lookup, `--exposure` score, `--gaps`, `--fusion` posteriors); the MCP server adds the stateful, iterative workflows (what-if hardening loops, ephemeral fingerprints, live two-domain compare). That folder's README has the breakdown. The portable [`AGENTS.md`](AGENTS.md) at the repo root is auto-detected by Kiro and other agents.md-aware tools.\n\n**Quickest install for AI clients with file-write tools.** Paste this prompt to your AI:\n\n\u003e Fetch `https://raw.githubusercontent.com/blisspixel/recon/main/agents/claude-code/skills/recon/SKILL.md` and save it to my Claude Code skills directory (`~/.claude/skills/recon/SKILL.md`), or to `~/.kiro/skills/recon/SKILL.md` if I'm using Kiro. Then run `pip install recon-tool` and `recon doctor` to verify.\n\nThe SKILL.md follows the open [agentskills.io](https://agentskills.io) standard, so the same file works in Claude Code and Kiro.\n\n## Automation and JSON\n\nrecon is built for piping, and the output shape depends on the command:\n`recon \u003cdomain\u003e --json` emits a single result object; `recon batch ... --json`\nemits a wrapped array (`--ndjson` gives one object per line); `recon delta`\nemits a DeltaReport. Validate any shape against\n[`docs/recon-schema.json`](docs/recon-schema.json)\n([raw URL](https://raw.githubusercontent.com/blisspixel/recon/main/docs/recon-schema.json));\nthe v2.0 stability contract and every field live in\n[`docs/schema.md`](docs/schema.md), and drift between schema and emitter is\ncaught by `tests/test_json_schema_file.py`.\n\nThe CLI also returns stable exit codes (`0` success, `1` general error,\n`2` validation, `3` no data, `4` internal) so a script can branch on the\noutcome without parsing output. Full contract:\n[`docs/schema.md`](docs/schema.md#exit-codes).\n\n## Limitations\n\nThe short version is below; [docs/limitations.md](docs/limitations.md) has the\nfull inventory, including known noise patterns and a guide to when to reach for\na different tool.\n\n- **Coverage depends on public DNS.** Organizations behind heavy proxies, with minimal DNS records, or that don't publish SaaS verification tokens will return sparse results. This is fundamental to passive-only collection. When sources transiently fail, the CLI tells you which one and why so you can retry or accept the partial answer.\n- **Internal workloads are structurally invisible.** Server-side API consumption (an org running internal Google Cloud ML, internal AWS data pipelines, internal Snowflake warehouses without public verification tokens, and so on) leaves no trace in public DNS, CT logs, or unauthenticated identity-discovery endpoints. recon cannot tell you what runs internally; it can only tell you what the org publishes externally. The CLI panel calls this out explicitly: the \"Cloud\" line surfaces what is observable, and on sparse-but-multi-domain apexes a one-line \"Passive-DNS ceiling\" footer notes that internal workloads and SaaS without DNS verification do not appear in public DNS records. A \"Multi-cloud\" indicator collapses sibling slugs (Route 53 + CloudFront = one AWS) when the public footprint touches more than one cloud vendor.\n- **Heuristic, not ground truth.** The fingerprint database and signal rules are rule-based and solo-maintained. Confident-looking output can still be wrong. The credible interval is the load-bearing field, not the point estimate: by construction, sparse evidence on hardened targets produces a wide interval rather than a confident-looking point estimate, and the `sparse=true` flag in the JSON output is the operator-facing signal that the layer has hit the passive-observation ceiling. Every detection in the catalog carries a description and a vendor doc URL, so a finding can be re-verified against the vendor's own documentation before action. Treat results as indicators for investigation, not as definitive assessments. Don't make business decisions based solely on this output. See [docs/correlation.md](docs/correlation.md) for the calibration principles the interval satisfies and the failure-mode catalog across hardening postures.\n\n## Development\n\n```bash\nuv sync                                # installs the dev group (pip: pip install -e . --group dev, pip 25.1+)\npytest tests/                          # full test suite\nruff check recon_tool/                 # lint\npyright recon_tool/                    # type check\npre-commit install                     # activate pre-commit hooks\n```\n\n## License\n\nMIT. See [LICENSE](LICENSE) for details.\n\nThis tool queries only public DNS records and unauthenticated endpoints. See [docs/legal.md](docs/legal.md) for full disclaimer.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblisspixel%2Frecon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblisspixel%2Frecon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblisspixel%2Frecon/lists"}