recon-tool 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. recon_tool-0.4.1/.github/workflows/ci.yml +72 -0
  2. recon_tool-0.4.1/.github/workflows/release.yml +102 -0
  3. recon_tool-0.4.1/.gitignore +49 -0
  4. recon_tool-0.4.1/CHANGELOG.md +163 -0
  5. recon_tool-0.4.1/CLAUDE.md +62 -0
  6. recon_tool-0.4.1/CONTRIBUTING.md +56 -0
  7. recon_tool-0.4.1/LICENSE +21 -0
  8. recon_tool-0.4.1/PKG-INFO +203 -0
  9. recon_tool-0.4.1/README.md +162 -0
  10. recon_tool-0.4.1/docs/fingerprints.md +54 -0
  11. recon_tool-0.4.1/docs/legal.md +30 -0
  12. recon_tool-0.4.1/docs/mcp.md +51 -0
  13. recon_tool-0.4.1/docs/roadmap.md +94 -0
  14. recon_tool-0.4.1/docs/signals.md +56 -0
  15. recon_tool-0.4.1/examples/README.md +8 -0
  16. recon_tool-0.4.1/examples/sample-batch.txt +9 -0
  17. recon_tool-0.4.1/examples/sample-output.json +50 -0
  18. recon_tool-0.4.1/pyproject.toml +90 -0
  19. recon_tool-0.4.1/recon_tool/__init__.py +10 -0
  20. recon_tool-0.4.1/recon_tool/cache.py +260 -0
  21. recon_tool-0.4.1/recon_tool/chain.py +204 -0
  22. recon_tool-0.4.1/recon_tool/cli.py +883 -0
  23. recon_tool-0.4.1/recon_tool/constants.py +27 -0
  24. recon_tool-0.4.1/recon_tool/data/fingerprints.yaml +1716 -0
  25. recon_tool-0.4.1/recon_tool/data/posture.yaml +218 -0
  26. recon_tool-0.4.1/recon_tool/data/signals.yaml +278 -0
  27. recon_tool-0.4.1/recon_tool/delta.py +148 -0
  28. recon_tool-0.4.1/recon_tool/fingerprints.py +390 -0
  29. recon_tool-0.4.1/recon_tool/formatter.py +1138 -0
  30. recon_tool-0.4.1/recon_tool/http.py +248 -0
  31. recon_tool-0.4.1/recon_tool/insights.py +398 -0
  32. recon_tool-0.4.1/recon_tool/merger.py +392 -0
  33. recon_tool-0.4.1/recon_tool/models.py +256 -0
  34. recon_tool-0.4.1/recon_tool/posture.py +375 -0
  35. recon_tool-0.4.1/recon_tool/resolver.py +318 -0
  36. recon_tool-0.4.1/recon_tool/server.py +526 -0
  37. recon_tool-0.4.1/recon_tool/signals.py +290 -0
  38. recon_tool-0.4.1/recon_tool/sources/__init__.py +5 -0
  39. recon_tool-0.4.1/recon_tool/sources/azure_metadata.py +82 -0
  40. recon_tool-0.4.1/recon_tool/sources/base.py +28 -0
  41. recon_tool-0.4.1/recon_tool/sources/dns.py +1123 -0
  42. recon_tool-0.4.1/recon_tool/sources/google.py +190 -0
  43. recon_tool-0.4.1/recon_tool/sources/google_identity.py +205 -0
  44. recon_tool-0.4.1/recon_tool/sources/oidc.py +119 -0
  45. recon_tool-0.4.1/recon_tool/sources/userrealm.py +176 -0
  46. recon_tool-0.4.1/recon_tool/validator.py +77 -0
  47. recon_tool-0.4.1/tests/__init__.py +1 -0
  48. recon_tool-0.4.1/tests/conftest.py +26 -0
  49. recon_tool-0.4.1/tests/test_batch.py +133 -0
  50. recon_tool-0.4.1/tests/test_chain.py +99 -0
  51. recon_tool-0.4.1/tests/test_cli.py +157 -0
  52. recon_tool-0.4.1/tests/test_cli_coverage.py +145 -0
  53. recon_tool-0.4.1/tests/test_crtsh.py +185 -0
  54. recon_tool-0.4.1/tests/test_custom_signals.py +136 -0
  55. recon_tool-0.4.1/tests/test_delta.py +146 -0
  56. recon_tool-0.4.1/tests/test_dns_subdetectors.py +403 -0
  57. recon_tool-0.4.1/tests/test_enrichment.py +77 -0
  58. recon_tool-0.4.1/tests/test_fingerprints.py +157 -0
  59. recon_tool-0.4.1/tests/test_formatter.py +202 -0
  60. recon_tool-0.4.1/tests/test_formatter_v2.py +289 -0
  61. recon_tool-0.4.1/tests/test_google_identity.py +276 -0
  62. recon_tool-0.4.1/tests/test_gws_features.py +740 -0
  63. recon_tool-0.4.1/tests/test_http.py +65 -0
  64. recon_tool-0.4.1/tests/test_http_advanced.py +228 -0
  65. recon_tool-0.4.1/tests/test_insights.py +224 -0
  66. recon_tool-0.4.1/tests/test_insights_unit.py +242 -0
  67. recon_tool-0.4.1/tests/test_integration.py +46 -0
  68. recon_tool-0.4.1/tests/test_merger.py +288 -0
  69. recon_tool-0.4.1/tests/test_models.py +122 -0
  70. recon_tool-0.4.1/tests/test_new_fingerprints_signals.py +66 -0
  71. recon_tool-0.4.1/tests/test_new_signals.py +52 -0
  72. recon_tool-0.4.1/tests/test_posture.py +102 -0
  73. recon_tool-0.4.1/tests/test_resolver.py +384 -0
  74. recon_tool-0.4.1/tests/test_security.py +119 -0
  75. recon_tool-0.4.1/tests/test_server.py +155 -0
  76. recon_tool-0.4.1/tests/test_server_cache.py +96 -0
  77. recon_tool-0.4.1/tests/test_signals.py +154 -0
  78. recon_tool-0.4.1/tests/test_signals_validation.py +72 -0
  79. recon_tool-0.4.1/tests/test_sources/__init__.py +1 -0
  80. recon_tool-0.4.1/tests/test_sources/test_azure_metadata.py +121 -0
  81. recon_tool-0.4.1/tests/test_sources/test_dns.py +278 -0
  82. recon_tool-0.4.1/tests/test_sources/test_oidc.py +257 -0
  83. recon_tool-0.4.1/tests/test_sources/test_userrealm.py +143 -0
  84. recon_tool-0.4.1/tests/test_userrealm_xml.py +77 -0
  85. recon_tool-0.4.1/tests/test_validator.py +219 -0
@@ -0,0 +1,72 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Set up Python
16
+ uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+
20
+ - name: Install dependencies
21
+ run: pip install -e ".[dev]"
22
+
23
+ - name: Lint
24
+ run: ruff check recon_tool/
25
+
26
+ typecheck:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - name: Set up Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version: "20"
35
+
36
+ - name: Set up Python
37
+ uses: actions/setup-python@v5
38
+ with:
39
+ python-version: "3.12"
40
+
41
+ - name: Install dependencies
42
+ run: pip install -e ".[dev]"
43
+
44
+ - name: Type check
45
+ run: pyright recon_tool/
46
+
47
+ test:
48
+ runs-on: ${{ matrix.os }}
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ os: [ubuntu-latest, windows-latest, macos-latest]
53
+ python-version: ["3.10", "3.11", "3.12"]
54
+ exclude:
55
+ - os: macos-latest
56
+ python-version: "3.10"
57
+ - os: windows-latest
58
+ python-version: "3.10"
59
+
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+
63
+ - name: Set up Python ${{ matrix.python-version }}
64
+ uses: actions/setup-python@v5
65
+ with:
66
+ python-version: ${{ matrix.python-version }}
67
+
68
+ - name: Install dependencies
69
+ run: pip install -e ".[dev]"
70
+
71
+ - name: Test
72
+ run: pytest tests/ --cov=recon_tool --cov-report=term-missing
@@ -0,0 +1,102 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write # Required for PyPI trusted publishing
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - name: Install dependencies
24
+ run: pip install -e ".[dev]"
25
+
26
+ - name: Run tests
27
+ run: pytest tests/ -q
28
+
29
+ - name: Lint
30
+ run: ruff check recon_tool/
31
+
32
+ build:
33
+ needs: test
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+
38
+ - name: Set up Python
39
+ uses: actions/setup-python@v5
40
+ with:
41
+ python-version: "3.12"
42
+
43
+ - name: Install build tools
44
+ run: pip install build
45
+
46
+ - name: Build package
47
+ run: python -m build
48
+
49
+ - name: Upload build artifacts
50
+ uses: actions/upload-artifact@v4
51
+ with:
52
+ name: dist
53
+ path: dist/
54
+
55
+ publish-pypi:
56
+ needs: build
57
+ runs-on: ubuntu-latest
58
+ environment: pypi
59
+ permissions:
60
+ id-token: write # Trusted publishing via OIDC
61
+ steps:
62
+ - name: Download build artifacts
63
+ uses: actions/download-artifact@v4
64
+ with:
65
+ name: dist
66
+ path: dist/
67
+
68
+ - name: Publish to PyPI
69
+ uses: pypa/gh-action-pypi-publish@release/v1
70
+
71
+ github-release:
72
+ needs: build
73
+ runs-on: ubuntu-latest
74
+ permissions:
75
+ contents: write
76
+ steps:
77
+ - uses: actions/checkout@v4
78
+
79
+ - name: Extract changelog
80
+ id: changelog
81
+ run: |
82
+ # Extract the section for this version from CHANGELOG.md
83
+ VERSION="${GITHUB_REF_NAME#v}"
84
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
85
+ # Grab everything between this version header and the next
86
+ awk "/^## \[${VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md > release_notes.md
87
+ cat release_notes.md
88
+
89
+ - name: Download build artifacts
90
+ uses: actions/download-artifact@v4
91
+ with:
92
+ name: dist
93
+ path: dist/
94
+
95
+ - name: Create GitHub Release
96
+ uses: softprops/action-gh-release@v2
97
+ with:
98
+ name: "v${{ steps.changelog.outputs.version }}"
99
+ body_path: release_notes.md
100
+ draft: false
101
+ prerelease: false
102
+ files: dist/*
@@ -0,0 +1,49 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+ *.egg
7
+ *.egg-info/
8
+ pip-log.txt
9
+ pip-delete-this-directory.txt
10
+
11
+ # Build
12
+ dist/
13
+ build/
14
+ *.whl
15
+
16
+ # Test / Coverage
17
+ .pytest_cache/
18
+ .hypothesis/
19
+ .coverage
20
+ .coverage.*
21
+ coverage.xml
22
+ htmlcov/
23
+
24
+ # Linting
25
+ .ruff_cache/
26
+
27
+ # IDE
28
+ .vscode/
29
+ .idea/
30
+ *.swp
31
+ *.swo
32
+
33
+ # OS
34
+ .DS_Store
35
+ Thumbs.db
36
+ Desktop.ini
37
+
38
+ # Env
39
+ .env
40
+ .venv/
41
+ venv/
42
+ env/
43
+
44
+ # Logs
45
+ *.log
46
+
47
+ # Kiro
48
+ .kiro/
49
+ /archive
@@ -0,0 +1,163 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.4.1] — 2026-04-11
9
+
10
+ ### Changed
11
+
12
+ - Added PyPI trusted publishing via GitHub Actions (OIDC, no API tokens).
13
+ - Added package metadata: classifiers, keywords, project URLs for PyPI listing.
14
+ - Fixed duplicate file warnings in wheel build by removing redundant `force-include`.
15
+
16
+ ## [0.4.0] — 2026-04-11
17
+
18
+ ### Added
19
+
20
+ - `--html` output — self-contained single-file HTML report with inline CSS, no JavaScript. Professional styling for sharing via email or archiving.
21
+ - `--csv` output for batch mode — flat CSV with one row per domain. Columns: domain, provider, display_name, tenant_id, auth_type, confidence, email_security_score, service_count, dmarc_policy, mta_sts_mode, google_auth_type.
22
+ - Lightweight local disk cache — `~/.recon/cache/` with configurable TTL (default 24h). CLI flags: `--no-cache` to bypass, `--cache-ttl` to override. JSON files on disk, lazy eviction, no external dependencies.
23
+ - `recon mcp` subcommand — start the MCP server from the CLI instead of `python -m recon_tool.server`.
24
+ - `recon doctor --fix` — scaffolds template `~/.recon/fingerprints.yaml` and `~/.recon/signals.yaml` with inline YAML comments explaining the format.
25
+
26
+ ### Changed
27
+
28
+ - Inference language tightened across insights and signals. Derived claims now use hedged language ("suggests," "indicators," "likely") instead of declarative phrasing. Factual observations (DMARC values, DKIM presence, email security scores) remain declarative.
29
+ - Removed `_preprocess_args()` sys.argv mutation hack. Domain shorthand routing (`recon pepsi.com`) now uses a custom Typer group with `resolve_command()` override — cleaner, safer for library imports, no global state mutation.
30
+ - `_SUBCOMMANDS` now includes `"mcp"`.
31
+ - Mutual exclusion enforced for output format flags (`--json`, `--md`, `--html`, `--csv`).
32
+
33
+ ## [0.3.0] — 2026-04-11
34
+
35
+ ### Added
36
+
37
+ - Google Workspace identity routing — new `GoogleIdentitySource` detects federated vs. managed auth by querying Google's public login flow. Extracts IdP name (Okta, Ping, Entra, etc.) for federated domains. Produces `google-federated`/`google-managed` slugs.
38
+ - Google Workspace CNAME module probing — detects active GWS modules (Mail, Calendar, Docs, Drive, Sites, Groups) via `ghs.googlehosted.com` CNAME resolution. Concurrent queries for all 6 prefixes.
39
+ - BIMI/VMC corporate identity extraction — fetches VMC certificates from BIMI `a=` URLs and extracts legally verified organization name, country, state, locality. Falls back to regex parsing when `cryptography` library is unavailable.
40
+ - Google site-verification token extraction — captures `google-site-verification` token values from TXT records for cross-domain organizational relationship mapping.
41
+ - MTA-STS policy fetch — when `_mta-sts` TXT record is found, fetches the policy file and extracts the mode (enforce/testing/none). Adds `mta-sts-enforce` slug for enforcing domains.
42
+ - TLS-RPT detection — detects `v=TLSRPTv1` records at `_smtp._tls.{domain}` with `tls-rpt` slug.
43
+ - Enhanced CSE config probing — extracts KACLS URL and multiple key service provider names from Google Workspace CSE configuration.
44
+ - Evidence traceability — new `EvidenceRecord` frozen dataclass captures source type, raw value, rule name, and slug for every detection. Propagated through the merge pipeline to `TenantInfo`. Included in `--json` output and `--verbose` display.
45
+ - Confidence separation — dual confidence model: `evidence_confidence` (how many sources contributed) and `inference_confidence` (strength of logical chain). Backward-compatible `confidence` field = min of both.
46
+ - Per-detection corroboration scoring — each detected slug gets a confidence score (high/medium/low) based on how many independent record types corroborate it.
47
+ - Fingerprint metadata enrichment — `provider_group` and `display_group` fields on fingerprint YAML entries. Formatter uses these for categorization, falling back to keyword heuristics.
48
+ - Cross-domain site-verification correlation in chain mode — domains sharing identical `google-site-verification` tokens are surfaced as organizationally related.
49
+ - 5 new Google Workspace signals: Google Workspace Full Suite, Google Federated Identity, Google MTA-STS Enforcing, plus updates to Google-Native Identity and Google Cloud Investment.
50
+ - 4 new posture rules: google_federated_identity, google_managed_identity, mta_sts_enforcing, tls_rpt_configured.
51
+ - Google Workspace insight generators: federated/managed identity insights, module summary insights.
52
+ - New data models: `EvidenceRecord`, `BIMIIdentity`. Extended `SourceResult`, `TenantInfo`, `Fingerprint` with new fields.
53
+ - 98 new tests (506 → 604 total). Test coverage 84%.
54
+
55
+ ### Changed
56
+
57
+ - `default_pool()` now includes `GoogleIdentitySource` (5 sources total).
58
+ - `merge_results()` propagates evidence, computes dual confidence, detection scores, and merges Google auth/BIMI/MTA-STS/site-verification data.
59
+ - `build_insights_with_signals()` accepts `google_auth_type` and `google_idp_name` parameters.
60
+ - `format_tenant_dict()` includes all new fields in JSON output.
61
+ - `format_tenant_markdown()` includes Google Workspace section and dual confidence.
62
+ - `render_tenant_panel()` shows GWS auth/modules, verbose evidence chains and detection scores.
63
+ - `lookup_tenant` MCP tool text format includes GWS auth and module summary.
64
+ - `_detect_email_security()` now also queries TLS-RPT, fetches MTA-STS policy, and parses BIMI VMC.
65
+ - `_detect_txt()` extracts site-verification tokens and creates evidence records.
66
+ - Fingerprints YAML: added `provider_group`/`display_group` to Microsoft 365, Google Workspace, and other key entries. Added TLS-RPT fingerprint.
67
+ - 29 signals (was 26). 22 posture rules (was 18).
68
+
69
+ ## [0.2.0] — 2026-04-11
70
+
71
+ ### Added
72
+
73
+ - Certificate intelligence — crt.sh metadata extraction (issuance velocity, issuer diversity, cert age, top issuers) from the existing crt.sh JSON response. No additional HTTP requests. Surfaced in panel, JSON, and markdown output.
74
+ - Metadata-aware signal engine — signals can now match on `dmarc_policy`, `auth_type`, `email_security_score`, `spf_include_count`, and `issuance_velocity` via YAML `metadata` conditions. Supports slug-only, metadata-only, and conjunction signals. 23 → 26 signals (4 layers).
75
+ - Neutral posture analysis — new `--posture` flag and `analyze_posture` MCP tool. Produces factual observations about domain configuration (email, identity, infrastructure, SaaS footprint, certificates, consistency) without attack/defense framing. YAML-driven rules in `data/posture.yaml` with `~/.recon/posture.yaml` additive override.
76
+ - Delta mode — `--compare previous.json` compares a live lookup against a previous JSON export. Surfaces added/removed services, slugs, signals, and scalar field changes (auth type, DMARC, confidence, domain count). Panel output with +/- markers, JSON output with structured diff.
77
+ - Recursive domain chaining — `--chain --depth N` (max 3) follows related domains via CNAME/CT breadcrumbs using BFS. 50-domain cap, visited-set deduplication, aggregate timeout. New `chain_lookup` MCP tool.
78
+ - 3 new metadata-aware signals: Federated Identity with Complex Email Delegation, Active Email Sending with Minimal Security, High Certificate Issuance Activity.
79
+ - 18 posture observation rules across 6 categories.
80
+ - 7 new frozen dataclasses: `CertSummary`, `MetadataCondition`, `SignalContext`, `Observation`, `DeltaReport`, `ChainResult`, `ChainReport`.
81
+ - 51 new tests (455 → 506 total). Test coverage 83%.
82
+
83
+ ### Changed
84
+
85
+ - `--full` now implies `--posture` in addition to `--services`, `--domains`, `--verbose`.
86
+ - `evaluate_signals()` now accepts a `SignalContext` instead of positional args. All callers updated.
87
+ - "Security Gap — Gateway Without DMARC Enforcement" signal moved from hardcoded Python check to YAML metadata conditions.
88
+ - `reload_data` MCP tool now also clears posture rule cache and reports posture rule count.
89
+ - README updated: broader audience description, new feature table rows, new CLI examples, new MCP tools listed.
90
+ - Roadmap updated: completed items marked, new future items added.
91
+
92
+ ## [0.1.3] — 2026-04-11
93
+
94
+ ### Added
95
+
96
+ - Common subdomain probing — ~35 high-signal prefixes (auth, login, sso, shop, api, status, cdn, etc.) are probed directly via DNS CNAME lookups. Works even when crt.sh is down.
97
+ - 30 new CNAME-based fingerprints for SaaS services discovered via subdomain CNAMEs: Okta (CNAME), Auth0, OneLogin, Salesforce Marketing Cloud, AWS ELB/S3/Elastic Beanstalk, Azure Front Door, Google Cloud Run/App Engine, Zendesk/Freshdesk (hosted), Contentful, Braze, Segment, Statuspage, LaunchDarkly, Cloudinary, Imgix, Optimizely, WalkMe, and more (156 → 186 total).
98
+ - crt.sh degraded notice — when crt.sh is unreachable, a subtle note appears in panel, markdown, and JSON output (`"partial": true`) so users know results may be incomplete.
99
+ - Lightweight subdomain enrichment — subdomains get CNAME+TXT-only lookups (2 queries each) instead of full DNS fingerprinting (~20 queries each), keeping enrichment fast.
100
+
101
+ ### Changed
102
+
103
+ - crt.sh subdomain cap raised from 20 to 100, with signal-based prioritization (auth/login/shop/api subdomains first, deep internal subdomains last).
104
+ - Enrichment cap raised from 10 to 25, with priority sorting so high-signal subdomains survive the cap.
105
+ - Two-tier enrichment: subdomains get lightweight CNAME+TXT lookups, separate domains get full DNS fingerprinting.
106
+ - Updated 8 signal rules to include new CNAME-detected slugs (imperva, auth0, onelogin, salesforce-mc, aws-elb, aws-s3, gcp-app, azure-fd, optimizely, walkme, braze, iterable, customerio, launchdarkly, contentful, etc.).
107
+
108
+ ## [0.1.2] — 2026-04-11
109
+
110
+ ### Added
111
+
112
+ - Google Workspace source — passive CSE config probing (`cse.{domain}/.well-known/cse-configuration`) for detecting Client-Side Encryption and external key managers.
113
+ - Google DKIM attribution — `google._domainkey` now adds the `google-workspace` slug, so Google Workspace is detected even when MX points to an email gateway (Proofpoint, Mimecast, Trend Micro, etc.).
114
+ - 4 new signal rules: Google-Native Identity, High-Security Posture (CSE), Google Cloud Investment, Dual Email Provider (13 → 24 total).
115
+ - Custom signals support via `~/.recon/signals.yaml` (additive, mirrors fingerprint extensibility).
116
+ - Certificate transparency integration via crt.sh for passive subdomain discovery.
117
+ - Expanded DKIM selector coverage — now checks common ESP selectors (Mailchimp, SendGrid, Mailgun, Postmark, Mimecast) in addition to Exchange and Google.
118
+ - SRV record detection for Microsoft Teams (legacy SIP/federation), XMPP, CalDAV, CardDAV.
119
+ - 13 new fingerprints: Box, Egnyte, Glean, Datadog, New Relic, PagerDuty, Render, Ping Identity, CyberArk, Lakera, Cato Networks, Rippling, Deel (143 → 156 total).
120
+ - `recon doctor` now checks crt.sh connectivity, signal database loading, and custom signals path.
121
+ - "Why recon?" comparison table in README.
122
+ - Expanded MCP Server section with setup steps, tools table, and config file locations per client.
123
+ - `CLAUDE.md` for Claude Code project context.
124
+ - `.kiro/steering/recon-project.md` for Kiro IDE context.
125
+ - `CHANGELOG.md`, `CONTRIBUTING.md`.
126
+ - `examples/` folder with sample JSON output and batch file (all fictional data).
127
+ - GitHub Actions CI workflow (Python 3.10–3.13, lint, type check, tests).
128
+
129
+ ### Changed
130
+
131
+ - Confidence scoring — M365 domains now reach High when OIDC tenant ID is corroborated by UserRealm (display name, auth type, or tenant domains). Previously required 2+ sources returning the same tenant ID, which never happened in practice.
132
+ - Non-M365 confidence — domains with 8+ DNS services and 2+ successful sources now reach High. Thresholds adjusted (was: 5 services for Medium, High unreachable).
133
+ - Skype for Business / Lync → Microsoft Teams — SRV records `_sip._tls` and `_sipfederationtls._tcp` pointing to `lync.com` now labeled as "Microsoft Teams" (deduplicated with CNAME-based detection). Microsoft retired Skype for Business Online in July 2021.
134
+ - Dual provider insight — shortened from "Hybrid/migration signal: Google email + Microsoft services detected" to "Dual provider: Google + Microsoft coexistence". No longer styled as a warning.
135
+ - Panel color palette — muted, modern tones replacing harsh ANSI primaries. Labels use `dim` instead of `bold`. Panel border is `dim`. Confidence colors: sage green (High), sky blue (Medium), terracotta (Low).
136
+ - Panel alignment — services and insights now use consistent label:value column alignment. Service continuation lines align under the first service name. Long insights word-wrap within the panel.
137
+ - All README examples now use fictional companies (Northwind Traders, Contoso, Fabrikam).
138
+ - README tagline updated to be more precise and humble.
139
+ - Panel output: fixed width (80 chars), related domains now dim instead of cyan.
140
+ - Updated Enterprise Security Stack, Zero Trust Posture, and Enterprise IT Maturity signals to include new security slugs.
141
+
142
+ ## [0.1.0] — 2026-04-10
143
+
144
+ ### Added
145
+
146
+ - Initial release.
147
+ - Domain intelligence CLI (`recon lookup`, `recon batch`, `recon doctor`).
148
+ - MCP server with `lookup_tenant` and `reload_data` tools.
149
+ - Three concurrent data sources: OIDC Discovery, GetUserRealm + Autodiscover, DNS records.
150
+ - 143 SaaS/service fingerprints in `data/fingerprints.yaml` across 14 categories.
151
+ - Signal intelligence engine with 3-layer evaluation (single-category, cross-category composites, consistency checks).
152
+ - Email security scoring (0–5) based on DMARC, DKIM, SPF strict, MTA-STS, BIMI.
153
+ - Related domain auto-enrichment from CNAME breadcrumbs.
154
+ - Custom fingerprint support via `~/.recon/fingerprints.yaml`.
155
+ - Rich terminal output with bordered panels, colored signals, and provider detection.
156
+ - Output formats: default panel, `--json`, `--md`, `--services`, `--full`, `--sources`.
157
+ - Batch mode with configurable concurrency (1–20) and ordered output.
158
+ - Input normalization (URLs, schemes, www prefix, paths, whitespace).
159
+ - SSRF protection in HTTP transport.
160
+ - Retry with exponential backoff on 429/503 responses.
161
+ - Structured exit codes (0, 2, 3, 4).
162
+ - `defusedxml` for safe XML parsing.
163
+ - Strict type checking with Pyright, linting with Ruff.
@@ -0,0 +1,62 @@
1
+ # recon
2
+
3
+ Passive domain intelligence CLI and MCP server. Queries public DNS records and unauthenticated Microsoft/Google endpoints — no credentials or API keys.
4
+
5
+ ## What it does
6
+
7
+ `recon <domain>` returns: company name, email provider, tenant ID, auth type, email security score (0-5), 186 SaaS service fingerprints, security stack detection, signal intelligence (AI adoption, GTM maturity, org size hints), and related domains (via CNAME breadcrumbs + certificate transparency + common subdomain probing).
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ recon northwindtraders.com # default panel output
13
+ recon northwindtraders.com --json # structured JSON
14
+ recon northwindtraders.com --md # markdown report
15
+ recon northwindtraders.com --full # everything
16
+ recon batch domains.txt --json # batch mode
17
+ recon doctor # connectivity check
18
+ ```
19
+
20
+ ## Project structure
21
+
22
+ - `recon_tool/` — source code
23
+ - `cli.py` — Typer CLI, entry point is `run()`
24
+ - `resolver.py` — orchestrates concurrent source queries
25
+ - `sources/` — OIDC, UserRealm, DNS lookup sources (DNS includes crt.sh cert transparency)
26
+ - `fingerprints.py` + `data/fingerprints.yaml` — SaaS detection (data-driven, no code changes needed)
27
+ - `signals.py` + `data/signals.yaml` — signal intelligence engine
28
+ - `insights.py` — derived intelligence from fingerprint matches
29
+ - `merger.py` — result merging, confidence scoring
30
+ - `formatter.py` — Rich terminal output, JSON, markdown
31
+ - `server.py` — MCP server (FastMCP, stdio transport)
32
+ - `http.py` — SSRF-safe HTTP client with retry/backoff
33
+ - `validator.py` — domain input validation
34
+ - `models.py` — frozen dataclasses (TenantInfo, SourceResult)
35
+ - `tests/` — 455 tests, pytest + hypothesis
36
+ - `data/fingerprints.yaml` — 186 SaaS fingerprints
37
+ - `data/signals.yaml` — 3-layer signal definitions (23 signals)
38
+
39
+ ## Development
40
+
41
+ ```bash
42
+ pip install -e ".[dev]"
43
+ pytest tests/ # run tests
44
+ ruff check recon_tool/ # lint
45
+ pyright recon_tool/ # type check
46
+ ```
47
+
48
+ ## Key patterns
49
+
50
+ - All source queries run concurrently via `asyncio.gather`
51
+ - Fingerprints and signals are YAML-driven — edit data files, not code
52
+ - Models are frozen dataclasses (immutable)
53
+ - HTTP transport has SSRF protection and retry with exponential backoff
54
+ - MCP server has TTL cache (120s) and per-domain rate limiting
55
+ - Custom fingerprints go in `~/.recon/fingerprints.yaml` (additive only)
56
+ - Custom signals go in `~/.recon/signals.yaml` (additive only)
57
+
58
+ ## Testing
59
+
60
+ - Integration tests are skipped by default (`-m 'not integration'`)
61
+ - Run `pytest -m integration` for network tests
62
+ - All examples in README use fictional companies (Northwind Traders, Contoso, Fabrikam)
@@ -0,0 +1,56 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in contributing to recon.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ git clone https://github.com/blisspixel/recon.git
9
+ cd recon
10
+ pip install -e ".[dev]"
11
+ pytest tests/
12
+ ```
13
+
14
+ ## Adding Fingerprints
15
+
16
+ The easiest way to contribute is adding new SaaS fingerprints. Edit `recon_tool/data/fingerprints.yaml`:
17
+
18
+ ```yaml
19
+ - name: Service Name
20
+ slug: service-slug # lowercase, unique identifier
21
+ category: Category Name # use an existing category if possible
22
+ confidence: high # high, medium, or low
23
+ detections:
24
+ - type: txt # txt, spf, mx, ns, cname, subdomain_txt, caa, srv
25
+ pattern: "^service-domain-verification="
26
+ description: What this record means
27
+ ```
28
+
29
+ Run `recon doctor` to validate your fingerprint loads correctly, then test against a domain you know uses the service.
30
+
31
+ ## Adding Signals
32
+
33
+ Custom signal rules go in `~/.recon/signals.yaml`:
34
+
35
+ ```yaml
36
+ signals:
37
+ - name: My Custom Signal
38
+ category: Custom
39
+ confidence: medium
40
+ description: What this signal means
41
+ requires:
42
+ any: [slug-a, slug-b, slug-c] # fingerprint slugs to match
43
+ min_matches: 2 # how many must be present
44
+ ```
45
+
46
+ ## Code Changes
47
+
48
+ - Run `ruff check recon_tool/` and `pyright recon_tool/` before submitting.
49
+ - Run `pytest tests/` to verify nothing breaks.
50
+ - Integration tests (`pytest -m integration`) require network access and are skipped by default.
51
+
52
+ ## Pull Requests
53
+
54
+ - Keep PRs focused — one feature or fix per PR.
55
+ - Fingerprint-only PRs are welcome and easy to review.
56
+ - Include a brief description of what you changed and why.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 recon-tool contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.