Mosint: Building a Speed-Layer Email OSINT Tool with Go Concurrency
Hook
A typical email investigation with sequential API calls takes 45-60 seconds. Mosint does it in under 5 seconds by querying everything at once—but that speed comes with architectural tradeoffs most developers don't see coming.
Context
Email OSINT has become critical infrastructure for security teams. Before launching a phishing simulation, investigating a suspicious account, or validating a potential data breach, security professionals need answers: Has this email been compromised? Where does it appear online? What social media accounts are linked to it? Traditionally, this meant manually visiting half a dozen websites—HaveIBeenPwned for breach data, Hunter.io for email validation, Pastebin search engines for leaked credentials, and various social media discovery tools. Python scripts emerged to automate this workflow, but they typically ran queries sequentially, bottlenecked by I/O wait times.
Mosint represents a architectural shift in OSINT tooling: instead of treating email investigation as a sequential pipeline, it treats it as a concurrency problem. Built in Go specifically to exploit goroutines and channels, Mosint fires off all API requests simultaneously and aggregates results as they arrive. For penetration testers working under time constraints or threat intelligence teams processing lists of indicators, this transforms email reconnaissance from a tedious bottleneck into a sub-five-second operation. The tool has gained significant traction in the security community (5,800+ GitHub stars) precisely because it solves the speed problem that Python-based alternatives couldn't crack without significantly more complexity.
Technical Insight
Mosint's architecture is a masterclass in pragmatic Go design for I/O-bound workloads. The core insight is recognizing that email OSINT is embarrassingly parallel—each API lookup is completely independent, so there's no reason to wait for Hunter.io before querying EmailRep or HaveIBeenPwned. The tool uses goroutines to spawn concurrent HTTP requests and channels to collect results without complex synchronization logic.
Here's the conceptual pattern (simplified from the actual codebase):
type OSINTResult struct {
Service string
Data interface{}
Error error
}
func investigateEmail(email string, config Config) []OSINTResult {
resultChan := make(chan OSINTResult, 10)
var wg sync.WaitGroup
services := []func(string, Config) OSINTResult{
checkHaveIBeenPwned,
checkEmailRep,
checkHunter,
checkIntelligenceX,
checkPastebin,
// ... more services
}
for _, service := range services {
wg.Add(1)
go func(fn func(string, Config) OSINTResult) {
defer wg.Done()
result := fn(email, config)
resultChan <- result
}(service)
}
go func() {
wg.Wait()
close(resultChan)
}()
var results []OSINTResult
for result := range resultChan {
results = append(results, result)
}
return results
}
This pattern lets Mosint launch 7-10 API calls simultaneously without blocking. The sync.WaitGroup ensures the main thread waits for all goroutines to complete before processing results, while the buffered channel prevents goroutines from blocking on send operations. Each service function handles its own HTTP client, authentication, and error conditions independently.
The configuration management is equally pragmatic. Rather than hardcoding API keys or requiring environment variables, Mosint reads from a YAML config file that maps service names to credentials:
hunter:
key: "your-hunter-api-key"
emailrep:
key: "your-emailrep-key"
intelx:
key: "your-intelligencex-key"
The tool gracefully degrades when API keys are missing—it simply skips those services and continues with available providers. This design decision reflects real-world usage: most users won't have subscriptions to all seven services, and forcing them to populate dummy values would create friction.
Output formatting demonstrates another thoughtful architectural choice. Mosint supports both human-readable terminal output (with color-coded sections) and structured JSON for pipeline integration. The JSON output is properly structured for downstream processing:
{
"email": "target@example.com",
"breaches": {
"haveibeenpwned": [
{"name": "LinkedIn", "date": "2021-06-22"},
{"name": "Dropbox", "date": "2012-07-01"}
]
},
"social_media": {
"instagram": true,
"twitter": true,
"linkedin": "https://linkedin.com/in/..."
},
"pastes": []
}
This dual-mode output makes Mosint equally useful for interactive terminal sessions and automated security pipelines that feed results into SIEM systems or threat intelligence platforms.
The Docker containerization adds operational maturity. Rather than requiring users to install Go, manage dependencies, and troubleshoot path issues, the Docker image packages everything into a reproducible environment. This is particularly valuable for security teams that need consistent tooling across multiple operator workstations or CI/CD pipelines running automated security checks.
Gotcha
The elephant in the room is API dependency hell. Mosint's core value proposition—comprehensive email intelligence—completely collapses without API keys. HaveIBeenPwned allows limited unauthenticated queries, but Hunter.io, EmailRep, and Intelligence X all require paid subscriptions with rate limits. A junior pentester who installs Mosint expecting plug-and-play functionality will get minimal results. This isn't clearly communicated in the repository's README, which showcases screenshots of rich data without emphasizing that those features require $50-200/month in API subscriptions. For organizations already invested in these services, Mosint is a force multiplier. For individual researchers or students, it's frustratingly limited.
The error handling story is surprisingly weak for a tool with nearly 6,000 stars. When an API is down, rate-limited, or returns malformed JSON, Mosint often fails silently or prints cryptic error messages. There's no retry logic, no exponential backoff for rate limits, and no intelligent fallback behavior. In production security workflows where you're investigating dozens or hundreds of emails, this brittleness means you'll need to wrap Mosint in additional error handling and logging infrastructure. The 'Scylla.so under construction' notice in the codebase suggests feature abandonment or maintenance debt—Scylla was a major breach database, and its absence is a significant gap. This raises questions about long-term sustainability: is this a maintained project or a point-in-time tool that happened to gain stars?
Verdict
Use if: You're a security professional or pentester with existing API subscriptions to Hunter.io, EmailRep, or Intelligence X who needs to shave 80% off email reconnaissance time. Mosint excels in time-constrained engagements (red team ops, incident response) where you need comprehensive email intelligence aggregated immediately, and you're willing to handle its rough edges with wrapper scripts. It's particularly valuable if you're building automated security pipelines that can consume structured JSON output. Skip if: You're expecting a free, fully-featured OSINT tool without API costs, need enterprise-grade error handling and logging, require deep customization of query logic, or want active development of new features. Individual researchers or students will find the API key requirements prohibitive. Consider theHarvester for broader OSINT without API dependencies, or Holehe if you specifically need account enumeration across hundreds of platforms without breach data.