dsieve: Taming Subdomain Chaos with Python-Style Slicing for Domain Lists
Hook
During a recent bug bounty reconnaissance on a major tech company, I discovered 47,000 subdomains. The real challenge wasn't finding them—it was making sense of their hierarchical structure to prioritize testing targets.
Context
Subdomain enumeration has become a cornerstone of modern penetration testing and bug bounty hunting. Tools like subfinder, amass, and assetfinder can discover thousands or even tens of thousands of subdomains for large organizations. But this abundance creates a new problem: subdomain overload. When you're staring at a text file with 50,000 lines of subdomains, where do you even start?
The challenge isn't just volume—it's structure. A subdomain like api-prod-v2.internal.kubernetes.aws.example.com contains multiple layers of organizational information. The third-level subdomain might reveal cloud infrastructure, the fourth might indicate environment, and the fifth might expose service architecture. Traditional Unix tools like grep, awk, and cut can slice these domains, but they require awkward regex patterns and intimate knowledge of domain structure. You need something that understands domain hierarchy natively and lets you navigate it intuitively. That's the gap dsieve fills: treating subdomain lists as structured, hierarchical data rather than flat text files.
Technical Insight
dsieve's core innovation is borrowing Python's slice notation for domain filtering. Instead of wrestling with regex or field separators, you use familiar syntax like -f 2:4 to extract subdomain levels. The tool parses each domain into components, numbers them from left to right (starting at 0), and applies your slice filter. This seemingly simple abstraction unlocks powerful filtering capabilities.
Here's a practical example. Suppose your reconnaissance generated a messy list mixing full URLs, bare domains, and deeply nested subdomains:
# domains.txt
https://www.example.com:443/path?query=1
api.example.com
v2.api.staging.internal.example.com
cdn.example.com
metrics.monitoring.prod.aws.example.com
Running dsieve with the -f 0:1 flag extracts only the first subdomain level:
cat domains.txt | dsieve -f 0:1
# Output:
www.example.com
api.example.com
v2.example.com
cdn.example.com
metrics.example.com
Notice how dsieve normalized the HTTPS URL by stripping the protocol, port, path, and query parameters automatically. It also flattened the deep subdomains by extracting just the slice you specified. The -f 0:1 notation means "give me subdomain levels 0 through 1" (exclusive of the endpoint, Python-style), which effectively captures the first subdomain component plus the root domain.
The enrichment feature (-e flag) works in reverse—it generates all parent domains from deep subdomains. This is invaluable for discovering intermediate infrastructure:
echo "dashboard.admin.v2.api.staging.internal.example.com" | dsieve -e
# Output:
example.com
internal.example.com
staging.internal.example.com
api.staging.internal.example.com
v2.api.staging.internal.example.com
admin.v2.api.staging.internal.example.com
dashboard.admin.v2.api.staging.internal.example.com
Each line represents a potential target. Maybe staging.internal.example.com has a wildcard DNS entry with a default virtual host. Maybe api.staging.internal.example.com exposes an unprotected GraphQL endpoint. Enrichment ensures you don't miss testing opportunities at intermediate levels.
The -top flag adds another dimension by ranking subdomains by the number of child domains they have. This is a proxy for organizational importance—subdomains with many children often represent major infrastructure branches:
cat large-subdomain-list.txt | dsieve -top 5
# Example output:
aws.example.com (1247 subdomains)
internal.example.com (892 subdomains)
prod.example.com (654 subdomains)
staging.example.com (421 subdomains)
dev.example.com (387 subdomains)
This ranking reveals attack surface density. The aws.example.com branch contains 1,247 child subdomains, suggesting significant cloud infrastructure. That's where you'd focus your attention first.
Under the hood, dsieve builds a tree structure to track parent-child relationships. When you pipe in subdomains, it parses each one, splits it into components, and maintains counts at each node. The implementation is straightforward Go—no external dependencies beyond the standard library. The entire binary compiles to around 2MB, making it trivial to deploy in Docker containers or CI/CD pipelines.
The tool's Unix philosophy shines in composition. You can chain it with other reconnaissance tools:
# Find all subdomains, filter to 3rd level, resolve live ones
subfinder -d example.com -silent | \
dsieve -f 0:2 | \
dnsx -silent -a -resp-only | \
sort -u > live-third-level.txt
This pipeline discovers subdomains, extracts the first two levels, validates they resolve, and outputs sorted unique results. Each tool does one thing well, and dsieve's stdin/stdout interface makes it a natural pipeline component.
Gotcha
dsieve operates purely on string manipulation—it never performs DNS lookups or validates that subdomains actually exist. This is by design (keeping the tool focused and fast), but it means you'll process plenty of dead domains. If you run dsieve -e on a list of discovered subdomains, you'll generate parent domains that might not have DNS records. You'll need a separate resolution step with tools like massdns or dnsx to filter the output to live hosts.
The -top ranking also has a subtle limitation: it counts immediate children, not recursive descendants. If aws.example.com has 10 direct children but each of those has 100 children of their own, the total branch size is actually 1,010 subdomains, but -top will only report 10. For deeply nested infrastructure, this can underestimate the true size of a subdomain branch. There's no recursive counting mode, so you'll need to mentally account for this when interpreting results. Additionally, the tool lacks advanced filtering like regex patterns, exclusion lists, or conditional logic. You can't say "give me all third-level subdomains except those matching 'test' or 'staging'" without piping to grep. For complex filtering workflows, you'll still need to combine dsieve with traditional Unix tools or write custom scripts.
Verdict
Use if: You're doing reconnaissance on large attack surfaces and need to quickly segment subdomain lists by hierarchy level, identify major infrastructure branches with -top, or generate parent domains from deep enumeration results. It's perfect for bug bounty hunters and pentesters who process thousands of subdomains and need a fast, intuitive way to prioritize testing targets. The Python slice notation makes it dramatically more ergonomic than sed/awk for domain-specific operations. Skip if: Your subdomain lists are small (under a few hundred entries) where manual inspection or simple grep is sufficient, you need DNS validation built-in (use dnsx or massdns instead), or you require complex filtering logic beyond hierarchical levels (you'll need regex tools or custom scripting). Also skip if you want a batteries-included enumeration suite—dsieve is a single-purpose filter, not a discovery tool.