Pius - Attack Surface Discovery & OSINT Reconnaissance Tool
May 26, 2026 · View on GitHub
Pius - Attack Surface Discovery & OSINT Reconnaissance Tool
Discover domains, subdomains, and IP ranges (CIDRs) owned by any organization using certificate transparency, RIR registries, passive DNS, and 26 extensible plugins.
Pius is an open-source attack surface discovery tool written in Go. Given a company name, it maps the complete external attack surface: domains, subdomains, and IP ranges (CIDRs). Pius queries certificate transparency logs, all five regional Internet registries (ARIN, RIPE, APNIC, AFRINIC, LACNIC), passive DNS databases, WHOIS/RDAP, BGP tables, and more through 26 discovery plugins.
Built for penetration testers, bug bounty hunters, and security teams who need reliable, repeatable asset discovery. Unlike ad-hoc reconnaissance scripts, Pius is production-grade: concurrent plugin execution, a three-phase discovery pipeline, multi-tier caching, confidence scoring for ambiguous results, graceful degradation, and passive-first OSINT defaults.
Table of Contents
- Why Pius: How It Compares to Amass and Subfinder
- Features
- Quick Start
- Plugins
- How It Works: Three-Phase Discovery Pipeline
- Architecture
- Usage
- Configuration
- FAQ
- Troubleshooting
- Contributing
- Security
- License
Why Pius: How It Compares to Amass and Subfinder
Pius fills the gap between subdomain enumeration tools (like subfinder) and full attack surface management platforms. If you need both domain and CIDR discovery from a single tool with confidence scoring and a phased pipeline, Pius is purpose-built for that workflow.
| Feature | Pius | amass | subfinder |
|---|---|---|---|
| Language | Go | Go | Go |
| Single binary | Yes | Yes | Yes |
| RIR CIDR discovery | Yes (all 5 RIRs) | Partial | No |
| Phase pipeline | Yes (handle → CIDR) | No | No |
| Confidence scoring | Yes | No | No |
| Passive mode default | Yes | Yes | Yes |
| Cache layer | Yes (24h) | No | No |
Features
Use Cases
- Penetration testing. Map an organization's external attack surface before an engagement.
- Bug bounty reconnaissance. Discover in-scope domains and IP ranges from an organization name.
- Attack surface management. Continuously monitor for new assets with passive-first defaults.
- Red team operations. Identify subsidiary and affiliated infrastructure through corporate registries (GLEIF, SEC EDGAR, Wikidata).
Capabilities
| Feature | Description |
|---|---|
| 26 Discovery Plugins | 17 domain plugins + 9 CIDR plugins covering certificate transparency, passive DNS, WHOIS, RDAP, RPSL, BGP tables, favicon hashing, and subdomain permutation |
| All 5 RIRs | ARIN (North America), RIPE (Europe/Middle East), APNIC (Asia-Pacific), AFRINIC (Africa), LACNIC (Latin America) |
| Three-Phase Pipeline | Phase 0 runs independently, Phase 1 discovers RIR org handles, Phase 2 resolves handles to CIDRs; late-stage plugins enrich results using discovered assets |
| Confidence Scoring | Ambiguous name-to-asset mappings are scored and flagged for review rather than silently dropped |
| Multi-Tier Cache | API responses cached 24h as JSON; RPSL databases cached 24h as decompressed local files |
| Passive Mode Default | Only OSINT sources queried by default; active plugins (DNS brute-force, zone transfer) opt-in |
| Flexible Output | Terminal table, JSON array, and NDJSON (newline-delimited) formats |
| Single Binary | Go-based tool compiles to one portable executable with no runtime dependencies |
Quick Start
Installation
Requires Go 1.25.0 or later.
go install github.com/praetorian-inc/pius/cmd/pius@latest
Or build from source:
git clone https://github.com/praetorian-inc/pius.git
cd pius
go build -o pius ./cmd/pius
Basic Usage
# Discover domains and CIDRs for an organization (passive mode)
pius run --org "Acme Corp"
# Add a domain hint to unlock more plugins
pius run --org "Acme Corp" --domain acme.com
# Include active plugins (DNS brute-force, zone transfer)
pius run --org "Acme Corp" --domain acme.com --mode all
Example Output
[domain] acme.com (crt-sh)
[domain] api.acme.com (crt-sh)
[domain] staging.acme.com (passive-dns)
[domain] acme.com (reverse-whois) ⚠ needs-review [confidence:0.42]
[cidr] 203.0.113.0/24 (arin)
[cidr] 198.51.100.0/22 (ripe)
List Available Plugins
pius list
Plugins
Domain Plugins
Most domain plugins run in Phase 0 (independent, concurrent). Late-stage plugins run in Phase 3. They emit discovered domain names.
| Plugin | Data Source | Auth Required | Mode | Notes |
|---|---|---|---|---|
crt-sh | Certificate Transparency logs | None | Passive | Deduplicates wildcard entries |
apollo | Apollo.io enrichment API | APOLLO_API_KEY | Passive | Caches results 24h; 0.85 confidence for domain queries |
github-org | GitHub organization search | GITHUB_TOKEN (optional) | Passive | Confidence-scored; 0.65 threshold to emit |
gleif | GLEIF LEI corporate registry | None | Passive | Discovers parent/subsidiary domains |
passive-dns | SecurityTrails passive DNS | SECURITYTRAILS_API_KEY | Passive | Historical subdomain records |
reverse-whois | ViewDNS reverse WHOIS | VIEWDNS_API_KEY | Passive | 0.75 confidence; registrant email matching |
whoxy-reverse-whois | Whoxy reverse WHOIS API | WHOXY_API_KEY | Passive | Paginated lookup; stale-record filter; 0.75 confidence |
builtwith | BuiltWith tag lookup API | BUILTWITH_API_KEY | Passive | Phase 3; correlates domains via shared analytics tracking codes |
dns-brute | Local DNS resolver | None | Active | 50 concurrent goroutines; embedded wordlist |
dns-zone-transfer | DNS AXFR | None | Active | Extracts A, AAAA, CNAME, MX, SRV records |
doh-enum | DNS-over-HTTPS resolvers | AWS credentials (optional) | Active | 50 concurrent workers; round-robin endpoint rotation; optional API Gateway deployment for IP diversity |
favicon-hash | Shodan + FOFA favicon search | SHODAN_API_KEY, FOFA_API_KEY (optional) | Active | MurmurHash3 of favicon; discovers origin IPs behind CDNs |
dns-permutation | Discovered subdomains (Phase 0) | None | Active | Phase 3; altdns-style permutations; wildcard filtering |
google-dorks | Google Knowledge Graph | None | Passive | Carousel scraping for subsidiary companies |
reverse-ip | PTR records, HackerTarget, ViewDNS | VIEWDNS_API_KEY (optional) | Passive | Phase 3; consumes CIDRs from Phase 2 |
wikidata | Wikidata SPARQL | None | Passive | P749/P355/P127 corporate relationships; 24h cache |
censys-org | Censys Platform API v3 | CENSYS_API_TOKEN, CENSYS_ORG_ID | Active | Searches host/cert data by org; emits domains + CIDRs; requires Starter+ plan; caches 24h |
CIDR Plugins
CIDR discovery uses a multi-phase pipeline: Phase 0 discovers CIDRs directly, Phase 1 discovers RIR organization handles, and Phase 2 resolves handles to CIDR blocks.
| Plugin | Phase | Data Source | Protocol | RIR Coverage |
|---|---|---|---|---|
asn-bgp | 0 (independent) | RIPE RIS BGP tables | HTTP REST | Global (announced prefixes) |
shodan | 0 (independent) | Shodan net: search | HTTP REST | Global (requires SHODAN_API_KEY) |
whois | 1 (handle discovery) | All 5 RIRs | HTTP REST | ARIN, RIPE, APNIC, AFRINIC, LACNIC |
edgar | 1 (handle discovery) | SEC EDGAR filings | HTTP REST | Global public companies |
arin | 2 (resolution) | ARIN RDAP | RDAP (RFC 7483) | North America |
ripe | 2 (resolution) | RIPE RDAP | RDAP (RFC 7483) | Europe, Middle East, Central Asia |
lacnic | 2 (resolution) | LACNIC RDAP | RDAP (RFC 7483) | Latin America & Caribbean |
apnic | 2 (resolution) | APNIC RPSL database | Cached gzip file | Asia-Pacific |
afrinic | 2 (resolution) | AFRINIC RPSL database | Cached gzip file | Africa |
How It Works: Three-Phase Discovery Pipeline
Pius uses a three-phase concurrent pipeline to discover organizational assets:
pius run --org "Acme Corp" --domain acme.com
│
▼
Plugin Registry
(init() auto-registration)
│
┌──────────┴─────────────────────────────┐
│ Phase 0 (concurrent, independent) │
│ crt-sh apollo github-org gleif │
│ passive-dns reverse-whois │
│ dns-brute* dns-zone-transfer* │
│ doh-enum* favicon-hash* │
│ asn-bgp │
└──────────┬─────────────────────────────┘
│ Emits domains + CIDRs directly
┌──────────┴─────────────────────────────┐
│ Phase 1 (concurrent) │
│ whois edgar │
└──────────┬─────────────────────────────┘
│ Emits RIR org handles
▼
enrichWithHandles()
Input.Meta["arin_handles"] = "ACME-1"
Input.Meta["ripe_handles"] = "ORG-ACME-RIPE"
│
┌──────────┴─────────────────────────────┐
│ Phase 2 (concurrent) │
│ arin ripe apnic afrinic lacnic │
└──────────┬─────────────────────────────┘
│ Emits CIDR blocks
▼
enrichWithAssets()
Input.Meta["cidrs"] = [...]
Input.Meta["discovered_domains"] = [...]
│
┌──────────┴─────────────────────────────┐
│ Late-stage (concurrent, asset consumers)│
│ dns-permutation* reverse-ip │
└──────────┬─────────────────────────────┘
│ Emits additional domains
▼
filterOutput()
(strips internal handle findings)
│
▼
Domains + CIDRs
* active mode only
Discovery Pipeline
- Phase 0 (Independent): Domain and CIDR plugins with no cross-plugin dependencies run concurrently from the start
- Phase 1 (Handle Discovery):
whoisqueries all 5 RIRs for organization handles.edgarpattern-matches SEC filings - Handle Enrichment: Discovered handles are grouped by registry and injected into the pipeline input
- Phase 2 (Handle Resolution): RDAP plugins (ARIN, RIPE, LACNIC) fetch CIDR blocks per handle. RPSL plugins (APNIC, AFRINIC) parse locally-cached registry databases
- Asset Enrichment: Discovered CIDRs and domains are injected into the pipeline input for late-stage consumers
- Late-Stage Enrichment:
dns-permutationgenerates altdns-style subdomain variants from discovered domains.reverse-ipperforms PTR lookups on discovered CIDRs - Output Filtering: Internal
cidr-handlefindings are removed. Only domains and CIDRs reach the user
Architecture
cmd/pius/ CLI entrypoint (Cobra-based)
pkg/
cache/ Two-tier caching: API responses (JSON) + RPSL databases (gzip)
cidr/ IP range → CIDR conversion and /24 subnet splitting
client/ Shared HTTP client with retries and 10 MB response limit
plugins/ Plugin interface, registry, confidence scoring
all/ Blank imports to trigger all plugin init() registrations
cidrs/ CIDR discovery plugin implementations
domains/ Domain discovery plugin implementations
runner/ Pipeline orchestration, mode filtering, output formatting
Key Design Decisions
- Three-phase pipeline separates RIR handle discovery (Phase 1) from CIDR resolution (Phase 2), enabling accurate multi-RIR lookups
- Plugin-style registration using Go
init()functions. New plugins require zero changes to the runner - Confidence scoring for ambiguous name-matching plugins (GitHub org search, reverse WHOIS, Apollo) distinguishes high-confidence results from ones that need human review
- Two-tier caching optimizes for different data profiles: small API responses as JSON (apollo, github-org) and large RPSL registry dumps as decompressed local files (APNIC, AFRINIC)
- Graceful degradation throughout. Plugin errors are logged but never fail the pipeline; partial results are always returned
Usage
Basic Discovery
# Passive discovery (default) is safe for continuous monitoring
pius run --org "Acme Corp"
# Add domain hint to unlock crt-sh, dns-brute, passive-dns, zone-transfer
pius run --org "Acme Corp" --domain acme.com
# Add ASN hint to directly query BGP tables
pius run --org "Acme Corp" --asn AS12345
# All hints combined
pius run --org "Acme Corp" --domain acme.com --asn AS12345
CIDR Discovery
# Passive CIDR discovery via all 5 RIRs
pius run --org "Acme Corp" --mode passive --plugins whois,arin,ripe,apnic,afrinic,lacnic
# Direct BGP lookup from ASN (no handle resolution needed)
pius run --org "Acme Corp" --asn AS12345 --plugins asn-bgp
DoH Subdomain Enumeration
# Basic DoH enumeration with embedded wordlist (Cloudflare, Google, AdGuard resolvers)
pius run --domain acme.com --mode active --plugins doh-enum
# Use a custom wordlist
pius run --domain acme.com --mode active --plugins doh-enum --doh-wordlist /path/to/wordlist.txt
# Use custom DoH servers
pius run --domain acme.com --mode active --plugins doh-enum \
--doh-servers "https://dns.google.com/dns-query,https://cloudflare-dns.com/dns-query"
# Deploy API Gateways across 8 AWS regions for IP rotation (requires AWS credentials)
pius run --domain acme.com --mode active --plugins doh-enum \
--doh-servers "https://dns.google.com/dns-query,https://cloudflare-dns.com/dns-query" \
--doh-deploy-gateways
# Use pre-existing API Gateway URLs
pius run --domain acme.com --mode active --plugins doh-enum \
--doh-gateways "https://abc123.execute-api.us-east-1.amazonaws.com/pius"
Output Formats
# Terminal table (default) - human-readable
pius run --org "Acme Corp"
# JSON array - structured output for parsing
pius run --org "Acme Corp" --output json
# NDJSON - one object per line, ideal for streaming/piping
pius run --org "Acme Corp" --output ndjson
# Pipe NDJSON to jq for filtering
pius run --org "Acme Corp" --output ndjson | jq 'select(.type == "cidr")'
Plugin Selection
# Run only specific plugins
pius run --org "Acme Corp" --plugins crt-sh,apollo,arin
# Disable specific plugins (run everything else)
pius run --org "Acme Corp" --disable edgar,dns-brute
# Active mode - includes DNS brute-force and zone transfer
pius run --org "Acme Corp" --domain acme.com --mode active
# All modes - passive + active combined
pius run --org "Acme Corp" --domain acme.com --mode all
# Adjust concurrency (default: 5)
pius run --org "Acme Corp" --concurrency 10
Configuration
Environment Variables
Plugins that require API keys check for them in Accepts() before running. If the environment variable is missing, the plugin is silently skipped.
| Variable | Plugin | Required | Notes |
|---|---|---|---|
APOLLO_API_KEY | apollo | Yes | Apollo.io API key |
GITHUB_TOKEN | github-org | No | Raises rate limit from 60 to 5000 req/hr |
SECURITYTRAILS_API_KEY | passive-dns | Yes | SecurityTrails API key |
VIEWDNS_API_KEY | reverse-whois | Yes | ViewDNS.info API key |
SHODAN_API_KEY | favicon-hash | Yes | Shodan API key |
FOFA_API_KEY | favicon-hash | No | FOFA API key; enables additional scanner |
VIEWDNS_API_KEY | reverse-ip | No | ViewDNS.info API key; enables additional reverse IP source |
CENSYS_API_TOKEN | censys-org | Yes | Censys Platform API Personal Access Token (Starter+ plan) |
CENSYS_ORG_ID | censys-org | Yes | Censys workspace organization UUID |
| AWS credentials | doh-enum | No | Required only when using --doh-deploy-gateways |
Cache
Pius caches data under ~/.pius/cache/ automatically. No configuration is needed.
| Cache Type | Used By | TTL | Format |
|---|---|---|---|
| API response cache | apollo, github-org, censys-org | 24 hours | JSON per key |
| RPSL registry database | apnic, afrinic | 24 hours | Decompressed gzip |
To clear the cache:
rm -rf ~/.pius/cache/
CLI Reference
Usage:
pius run [flags]
pius list
run flags:
-o, --org string Organization name to search (required)
-d, --domain string Known domain hint (optional)
--asn string Known ASN hint, e.g. AS12345 (optional)
--plugins string Comma-separated plugin whitelist (default: all)
--disable string Comma-separated plugin blacklist
--concurrency int Max concurrent plugins (default: 5)
-f, --output string Output format: terminal, json, ndjson (default: terminal)
--mode string Plugin mode: passive, active, all (default: passive)
--doh-wordlist string Path to subdomain wordlist for DoH enumeration
--doh-servers string Comma-separated DoH server URLs
--doh-gateways string Comma-separated AWS API Gateway URLs for DoH
--doh-deploy-gateways Auto-deploy AWS API Gateways for IP rotation
Exit Codes:
| Code | Meaning |
|---|---|
| 0 | Success, discovery completed |
| 1 | Runtime error |
FAQ
Which Pius plugins run by default without API keys?
All passive plugins that accept the provided input run by default. Passive plugins with API key requirements (apollo, passive-dns, reverse-whois) are silently skipped if their environment variable is not set. Active plugins (dns-brute, dns-zone-transfer, doh-enum, favicon-hash) only run with --mode active or --mode all.
How does Pius discover IP ranges and CIDRs?
Phase 0 plugins (domain plugins + asn-bgp) run immediately and concurrently. Phase 1 plugins (whois, edgar) discover RIR organization handles from the company name. The runner then injects those handles into the input as metadata, and Phase 2 plugins (arin, ripe, apnic, afrinic, lacnic) resolve each handle to CIDR blocks. This separation enables accurate multi-RIR coverage while keeping plugins loosely coupled.
What does the needs-review confidence flag mean?
Some plugins use confidence scoring to rank ambiguous matches. For example, github-org scores organization candidates based on name similarity and domain matching. Findings with confidence between 0.35 and 0.65 are emitted with a needs-review flag rather than being silently discarded. Findings below 0.35 are dropped as noise.
How do I write a custom Pius plugin?
- Create a Go file in
pkg/plugins/domains/orpkg/plugins/cidrs/ - Implement the
plugins.Plugininterface (7 methods:Name,Description,Category,Phase,Mode,Accepts,Run) - Register in an
init()function:func init() { plugins.Register("my-plugin", func() plugins.Plugin { return &MyPlugin{client: client.New()} }) } - Import the package in
pkg/plugins/all/all.go
See existing plugins like crt_sh.go or arin.go for reference implementations.
Can Pius run without any API keys?
Yes. The following plugins require no authentication and run with only --org:
crt-sh(needs--domain)gleifwhoisedgararin,ripe,apnic,afrinic,lacnicasn-bgp(needs--asn)github-org(optionalGITHUB_TOKEN)wikidatagoogle-dorks
Active plugins (dns-brute, dns-zone-transfer, doh-enum) also require no auth but must be enabled with --mode active. Note: doh-enum uses an embedded wordlist by default; AWS credentials are only needed for --doh-deploy-gateways. The favicon-hash plugin requires SHODAN_API_KEY.
What is the difference between RDAP and RPSL for IP range discovery?
RDAP plugins (arin, ripe, lacnic) make live HTTP queries to each registry's RDAP API. One request is made per handle. RPSL plugins (apnic, afrinic) download the full registry database as a gzip file once per day and parse it locally. RPSL offers lower latency after the initial download; RDAP offers fresher data.
Troubleshooting
No CIDR results
Cause: Phase 1 plugins found no RIR handles, or handles returned no CIDRs.
Solutions:
- Try alternate spellings of the organization name:
--org "Acme Corporation"vs--org "Acme Corp" - Check if
whoisoredgarran: run with--plugins whoisto isolate - Verify the organization has RIR allocations (some orgs use cloud provider space)
No domain results
Cause: Missing domain hint, or API keys not set.
Solutions:
- Add
--domainto unlock crt-sh and DNS plugins - Set
APOLLO_API_KEY,SECURITYTRAILS_API_KEY, orVIEWDNS_API_KEYfor those plugins - Run
pius listto confirm which plugins are registered
APNIC/AFRINIC results are stale
Cause: RPSL database cache is within its 24-hour TTL.
Solution:
rm ~/.pius/cache/*.rpsl
pius run --org "Acme Corp"
Rate limiting from GitHub
Cause: GITHUB_TOKEN not set; unauthenticated requests limited to 60/hr.
Solution:
export GITHUB_TOKEN="ghp_..."
pius run --org "Acme Corp"
Slow CIDR discovery
Cause: Multiple RDAP requests per handle across multiple registries.
Solution: Reduce concurrency or restrict to specific registries:
# Only query ARIN (faster if org is US-based)
pius run --org "Acme Corp" --plugins whois,arin
Contributing
We welcome contributions. To add a new plugin:
- Create the plugin file in the appropriate package (
domains/orcidrs/) - Implement the
Plugininterface - 7 methods required - Register via
init()and add a blank import topkg/plugins/all/all.go - Write unit tests covering
Accepts(),Run(), error paths, and caching (if applicable) - Follow existing error handling conventions:
- Transient failures → return
(nil, nil)(graceful degradation) - Parse errors → return wrapped error with context
- Log warnings with
slog.Warn()for partial failures
- Transient failures → return
Development
# Run all tests
go test ./...
# Run specific package tests
go test ./pkg/plugins/domains/... -v
# Build binary
go build -o pius ./cmd/pius
# Install to $GOPATH/bin
go install ./cmd/pius
Security
Pius is designed for authorized security testing and asset discovery only.
- Pius sends DNS queries and API requests for the organization you specify. You must always ensure you have authorization
- Active plugins (
dns-brute,dns-zone-transfer) generate network traffic to target nameservers - Never run against organizations you don't own or have explicit permission to assess
Report security issues via GitHub Issues.
License
Apache 2.0 - Praetorian Security, Inc.
Built by Praetorian. Offensive security experts specializing in attack surface management, penetration testing, and security engineering.